%CODEGENERATOR Class for code generation
%
% Objects of the CodeGenerator class automatcally generate robot specific
% code, as either M-functions, C-functions, C-MEX functions, or real-time
% capable Simulink blocks.
%
% The various methods return symbolic expressions for robot kinematic and
% dynamic functions, and optionally support side effects such as:
% - M-functions with symbolic robot specific model code
% - real-time capable robot specific Simulink blocks
% - mat-files with symbolic robot specific model expressions
% - C-functions and -headers with symbolic robot specific model code
% - robot specific MEX functions based on the generated C-code (C-compiler
%   must be installed).
%
% Example::
%
%        % load robot model
%        mdl_twolink
%
%        cg = CodeGenerator(twolink);
%        cg.geneverything();
%
%        % a new class has been automatically generated in the robot directory.
%        addpath robot
%
%        tl = @robot();
%        % this class is a subclass of SerialLink, and thus polymorphic with
%        % SerialLink but its methods have been overloaded with robot-specific code,
%        % for example
%        T = tl.fkine([0.2 0.3]);
%        % uses concise symbolic expressions rather than the generalized A-matrix
%        % approach
%
%        % The Simulink block library containing robot-specific blocks can be
%        % opened by
%        open robot/robotslib.slx
%        % and the blocks dragged into your own models.
%
% Methods::
%
%  gencoriolis     generate Coriolis/centripetal code
%  genfdyn         generate forward dynamics code
%  genfkine        generate forward kinematics code
%  genfriction     generate joint friction code
%  gengravload     generate gravity load code
%  geninertia      generate inertia matrix code
%  geninvdyn       generate inverse dynamics code
%  genjacobian     generate Jacobian code
%  geneverything   generate code for all of the above
%
% Properties (read/write)::
%
%  basepath       basic working directory of the code generator
%  robjpath       subdirectory for specialized MATLAB functions
%  sympath        subdirectory for symbolic expressions
%  slib           filename of the Simulink library
%  slibpath       subdirectory for the Simulink library
%  verbose        print code generation progress on console (logical)
%  saveresult     save symbolic expressions to .mat-files (logical)
%  logfile        print modeling progress to specified text file (string)
%  genmfun        generate executable M-functions (logical)
%  genslblock     generate Embedded MATLAB Function blocks (logical)
%  genccode       generate C-functions and -headers (logical)
%  genmex         generate MEX-functions as replacement for M-functions (logical)
%  compilemex     automatically compile MEX-functions after generation (logical)
%
% Properties (read only)::
%  rob            SerialLink object to generate code for (1x1).
%
% Notes::
%  - Requires the MATLAB Symbolic Toolbox.
%  - For robots with > 3 joints the symbolic expressions are massively
%    complex, they are slow and you may run out of memory.
%  - As much as possible the symbolic calculations are down row-wise to
%    reduce the computation/memory burden.
%  - Requires a C-compiler if robot specific MEX-functions shall be
%    generated as m-functions replacement (see MATLAB documentation of MEX
%    files).
%
% Author::
%  Joern Malzahn, (joern.malzahn@tu-dortmund.de)
%
% See also SerialLink, Link.

% Copyright (C) 1993-2012, by Peter I. Corke
% Copyright (C) 2012-2014, by Joern Malzahn
%
% This file is part of The Robotics Toolbox for Matlab (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB. If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
%
% The code generation module originally emerged during the work on a project
% funded by the German Research Foundation (DFG, BE1569/7-1). The authors
% gratefully acknowledge the financial support.

classdef CodeGenerator
    properties (SetAccess = private)
        rob
        ccodepath;
        cppcodepath;
        robjpath;
        sympath;
        slibpath;
    end
    properties
        basepath;
        slib;
        verbose;
        saveresult;
        logfile;
        genmfun;
        genslblock;
        genccode;
        genmex;
        compilemex;
    end
    properties (GetAccess = private)
        debug;        % just appears because of tb_optparse, so hide it from the user
    end
    methods

        function CGen = CodeGenerator(rob,varargin)
        %CodeGenerator.CodeGenerator Construct a code generator object
        %
        % cGen = CodeGenerator(ROB, OPTIONS) is a code generator object for the SerialLink
        % object ROB.
        %
        %
        % Options::
        %
        % CodeGenerator has many options, and useful sets of options are called
        % optionSets, and the following are recognized:
        %
        %  'default'     set the options: verbose, saveResult, genMFun, genSLBlock
        %  'debug'       set the options: verbose, saveResult, genMFun, genSLBlock
        %                and create a logfile named 'robModel.log' in the working directory
        %  'silent'      set the options: saveResult, genMFun, genSLBlock
        %  'disk'        set the options: verbose, saveResult
        %  'workspace'   set the option: verbose; just outputs symbolic expressions to workspace
        %  'mfun'        set the options: verbose, saveResult, genMFun
        %  'slblock'     set the options: verbose, saveResult, genSLBlock
        %  'ccode'       set the options: verbose, saveResult, genCcode
        %  'mex'         set the options: verbose, saveResult, genMEX
        %
        % If no optionSet is provided, then 'default' is used.
        %
        % The options themselves control the code generation and user information:
        %
        %  'verbose'           write code generation progress to command window
        %  'saveResult         save results to hard disk (always enabled, when genMFun and genSLBlock are set)
        %  'logFile',logfile   write code generation progress to specified logfile
        %  'genMFun'           generate robot specific m-functions
        %  'genSLBlock'        generate real-time capable robot specific Simulink blocks
        %  'genccode'          generate robot specific C-functions and -headers
        %  'mex'               generate robot specific MEX-functions as replacement for the m-functions
        %  'compilemex'        select whether generated MEX-function should be compiled directly after generation
        %
        %  Any option may also be modified individually as optional parameter value pairs.
        %
        % Author::
        %  Joern Malzahn
        %  2012 RST, Technische Universitaet Dortmund, Germany.
        %  http://www.rst.e-technik.tu-dortmund.de

            if ~isa(rob,'SerialLink')
                error('CodeGenerator:wrongConstructorInput','The input variable %s must be a SerialLink object.',inputname(1));
            end

            if ~rob.issym
                CGen.rob = rob.sym;
            else
                CGen.rob = rob;
            end

            % defaults
            CGen.basepath = fullfile(CGen.getrobfname);
            CGen.robjpath = fullfile(CGen.basepath,['@',CGen.getrobfname]);
            CGen.sympath = fullfile(CGen.basepath,'symbolicexpressions');
            CGen.slib = [CGen.getrobfname,'slib'];
            CGen.slibpath = fullfile(CGen.basepath,CGen.slib);
            CGen.verbose = false;
            CGen.saveresult = false;
            CGen.logfile = '';
            CGen.genmfun = false;
            CGen.genslblock = false;
            CGen.debug = false;
            CGen.genccode = false;
            CGen.ccodepath = fullfile(CGen.basepath,'c');
            CGen.cppcodepath = fullfile(CGen.basepath,'cpp');
            CGen.genmex = false;
            CGen.compilemex = true;

            if nargin < 2
                varargin{1} = 'default';
            end

            % Determine code generation option set
            switch lower(varargin{1})
                case 'default'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult','genmfun','genslblock'},varargin(2:end)]);
                case 'debug'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult','genmfun','genslblock','logfile','robModel.log'},varargin(2:end)]);
                case 'silent'
                    CGen = tb_optparse(CGen,...
                        [{'saveresult','genmfun','genslblock'},varargin(2:end)]);
                case 'disk'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult'},varargin(2:end)]);
                case 'workspace'
                    CGen = tb_optparse(CGen,...
                        [{'verbose'},varargin(2:end)]);
                case 'mfun'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult','genmfun'},varargin(2:end)]);
                case 'slblock'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult','genslblock'},varargin(2:end)]);
                case 'ccode'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult','genmfun','logfile','robModel.log','genccode'},varargin(2:end)]);
                case 'mex'
                    CGen = tb_optparse(CGen,...
                        [{'verbose','saveresult','genmfun','logfile','robModel.log','genmex'},varargin(2:end)]);
                otherwise
                    CGen = tb_optparse(CGen,varargin);
            end

            if any([CGen.genmfun, CGen.genslblock, CGen.genccode, CGen.genmex])
                CGen.saveresult = true;
            end

            if CGen.genmex
                CGen.genccode = true;
            end

            if ~isempty(CGen.logfile)
                logfid = fopen(CGen.logfile,'w+'); % open or create file, discard existing contents
                fclose(logfid);
            end
            CGen.logmsg([datestr(now),' +++++++++++++++++++++++++++++++++++\n']);
            CGen.logmsg([datestr(now),'\tLog for ',CGen.getrobfname,'\n']);
            CGen.logmsg([datestr(now),' +++++++++++++++++++++++++++++++++++\n']);

        end

        function robName = getrobfname(CGen)

        % Use regular expression \W to replace any character
        % that is not alphabetic, numeric, or underscore.
        % For English character sets, this is equivalent to [^a-zA-Z_0-9].
        % This yields proper variable and function names!
            robName = regexprep(CGen.rob.name, '\W', '');

            if numel(robName)>4 && strcmp(robName(end-3:end),'copy')
                robName = robName(1:end-4);
            end
        end

        function savesym(CGen,sym2save, symname, fname)
            if ~exist(CGen.sympath,'dir')
                mkdir(CGen.sympath)
            end

            eval([symname,'= sym2save;']);
            save(fullfile(CGen.sympath,fname),symname);
        end

        function [] = geneverything(CGen)
            [t,allT] = CGen.genfkine;
            [J0,Jn] = CGen.genjacobian;
            [G] = CGen.gengravload;
            [I] = CGen.geninertia;
            [C] = CGen.gencoriolis;
            [F] = CGen.genfriction;
            [Iqdd] = CGen.genfdyn;
            [tau] = CGen.geninvdyn;
        end

        function CGen = set.genmfun(CGen,value)
            CGen.genmfun = value;
            if value == true
                CGen.saveresult = value;
            end

            if ~exist(fullfile(CGen.robjpath,CGen.getrobfname),'file')
                CGen.logmsg([datestr(now),'\tCreating ',CGen.getrobfname,' m-constructor ']);
                CGen.createmconstructor;
                CGen.logmsg('\t%s\n',' done!');
            end
        end

        function CGen = set.genslblock(CGen,value)
            CGen.genslblock = value;
            if value == true
                CGen.saveresult = true;
            end
        end
        function [] = addpath(CGen)
        %CodeGenerator.addpath Adds generated code to search path
        %
        % cGen.addpath() adds the generated m-functions and block library to the
        % MATLAB function search path.
        %
        % Author::
        %  Joern Malzahn
        %  2012 RST, Technische Universitaet Dortmund, Germany.
        %  http://www.rst.e-technik.tu-dortmund.de
        %
        % See also addpath.
        addpath(CGen.basepath);
        end

        function [] = rmpath(CGen)
        %CodeGenerator.rmpath Removes generated code from search path
        %
        % cGen.rmpath() removes generated m-functions and block library from the
        % MATLAB function search path.
        %
        % Author::
        %  Joern Malzahn
        %  2012 RST, Technische Universitaet Dortmund, Germany.
        %  http://www.rst.e-technik.tu-dortmund.de
        %
        % See also rmpath.
        rmpath(CGen.basepath);
        end

        function [] = purge(CGen,varargin)
        %CodeGenerator.purge  Cleanup generated files
        %
        % cGen.purge() deletes all generated files, first displays a question dialog to
        % make sure the user really wants to delete all generated files.
        %
        % cGen.purge(1) as above but skips the question dialog.
        %
        % Author::
        %  Joern Malzahn
        %  2012 RST, Technische Universitaet Dortmund, Germany.
        %  http://www.rst.e-technik.tu-dortmund.de
            dopurge = 0;

            if exist(CGen.basepath,'dir')
                if nargin > 1
                    dopurge = varargin{1}
                else
                    qstn = ['Do you really want to delete ',CGen.basepath, ' and all of it''s contents?'];
                    tit = ['Purge: ',CGen.getrobfname];
                    str1 = 'Yes';
                    str2 = 'No';
                    button = questdlg(qstn,tit,str1,str2,str1)
                    dopurge = strcmp(button,str1);
                end
            end

            if dopurge
                bdclose all

                warning off;
                CGen.rmpath;
                warning on;

                rmdir(CGen.basepath,'s')
                if ~isempty(CGen.logfile) && exist(CGen.logfile,'file')
                    delete(CGen.logfile);
                end
            end
        end
    end
end


function SlabAnalysis(mCatalog,vCoastlines,vFaults,vVolcano)
% % Example: SlabAnalysis(a,coastline,faults,vo)
% -------------------------------------------------------------------------------------------------------------
% Creates a cell-array with subcatalogs for every grid node defined by mPolygon. These subcatalogs
%   contain only indices to the earthquake "rows" in mCatalog.
%
% Input parameters:
%   params.mCatalog             Earthquake catalog
%   params.vCoastlines          Coastlines
%   params.vFaults              Faults
%   params.vVolcano             Volcano
%
% Output parameters:
%   none
%
% Thomas van Stiphout
% February 28, 2006
% -------------------------------------------------------------------------------------------------------------
%

if ~strcmp(get(gcf,'name'),'3DResult plot')
% Launch GUI
hMenuFig = gui_slab;
handles = guidata(hMenuFig);

% Analyze Output
if ~ishandle(hMenuFig)
    %     handles.answer = 0;
elseif (handles.answer==0)
    disp('Canceled SlabAnalysis - Goodbye');
elseif (handles.answer==1)
    % define equidistance btw gridpoints
    params.nDx=str2double(get(handles.nDx,'String'));
    params.nDy=params.nDx;
    % Define the percentile of the depth values
    params.vPercentiles=str2double(get(handles.vPerc,'String'));
    % Radius for Map-Gridding for Columns
    params.fColRadius=str2double(get(handles.fRadius,'String'));
    % Minimum number of events that have to be in the column
    params.nColMinEvents=str2double(get(handles.nMinColEvents,'String'));
    % Volume sampling is cylindrical
    params.bCylSmp=get(handles.chkCylSmp,'Value');
    params.bCylSmpModeN=get(handles.radCylSmpModeN,'Value');
    params.bCylSmpModeR=get(handles.radCylSmpModeR,'Value');
    params.fCylSmpValue=str2double(get(handles.fCylSmpValue,'String'));
    params.fCylSmpBnd=str2double(get(handles.fCylSmpBnd,'String'));
    if ((params.bCylSmpModeN==1) && (params.bCylSmpModeR==0))
        params.nGriddingMode=1; % constant numbers
        params.nNumberEvents=params.fCylSmpValue;
    elseif ((params.bCylSmpModeN==0) && (params.bCylSmpModeR==1))
        params.nGriddingMode=0; % constant radius
    else
        disp('Something is going wrong');
    end
    % Volume sampling is 3D-spherical
    params.b3DSmp=get(handles.chk3DSmp,'Value');
    params.b3DSmpModeN=get(handles.radCylSmpModeN,'Value');
    params.b3DSmpModeR=get(handles.radCylSmpModeR,'Value');
    params.f3DSmpValue=str2double(get(handles.fCylSmpValue,'String'));
    params.f3DSmpBnd=str2double(get(handles.fCylSmpBnd,'String'));
    if ((params.bCylSmpModeN==1) && (params.bCylSmpModeR==0))
        params.n3DGriddingMode=3; % constant numbers
        params.nNumberEvents=params.fCylSmpValue;
    elseif ((params.bCylSmpModeN==0) && (params.bCylSmpModeR==1))
        params.n3DGriddingMode=4; % constant radius
    else
        disp('Something is going wrong');
    end
    %     close(get(handles.figure1,'Name'));

    if (params.bCylSmp==1)
        if ~exist('Name')
            Name=cellstr('Cylindrical Volume Sampling');
        else
            Name(size(Name,1)+1,1)=cellstr('Cylindrical Volume Sampling');
        end
    end
    if params.b3DSmp
        if ~exist('Name')
            Name=cellstr('3D-Spherical Volume Sampling');
        else
            Name(size(Name,1)+1,1)=cellstr('3D Spherical Volume Sampling');
        end
    end

    params.Name=Name;
    params.mCatalog=mCatalog;
    params.vCoastline=vCoastlines;
    params.vFaults=vFaults;
    params.vVolcanoes=vVolcano;
    params.chkVolcanoes=1;

    clear mCatalog vCoastlines vFaults vVolcano
    % Create grid
    params.bMap=1;
    params.nGriddingMode=1;
    params.fSizeRectHorizontal=nan;
    params.fSizeRectDepth=nan;
    params.fSizeRectHorizontal=nan;
    params.fSizeRectDepth=nan;

    % Create map-gridding
    % by defining equidistance btw gridpoints

    % Short distance conversion
    params.fDLon=km2deg(params.nDx);
    params.fDLat=km2deg(params.nDy);
    %
    hFigure=gcf;

    % Select grid from seismicity map
    [params.mPolygon, params.vX, params.vY, params.vUsedNodes] = ex_selectgrid(hFigure, params.fDLon, params.fDLat, 0);

    % Sampling Radius is set equally to the grid raster; indices for each grid point
    [params.caNodeIndices params.vResolution] = ex_CreateIndexCatalog2(params.mCatalog, params.mPolygon, 1, 1, ...
        [], params.fColRadius, params.fSizeRectHorizontal, params.fSizeRectDepth);

    % preparing the matrix containing the depth-levels according to the
    % percentiles defined
    params.mDepths=ones(length(params.mPolygon),length(params.vPercentiles))*nan;
    params.mValueGrid=ones(length(params.mPolygon),1)*nan;

    % calculation the depths-levels according to the percentiles for each gridpoint
    for i=1:length(params.mPolygon)
        params.mDepths(i,:)=prctile(params.mCatalog(params.caNodeIndices{i},7),params.vPercentiles) ;
        %     params.mValueGrid(i)=length(params.mCatalog(params.caNodeIndices{i}));
    end

    % Take only depth values that are well constrained,
    % i.e. with at least 50 earthquakes per map-node; set others to NaN
    params.mDepths((params.vResolution <= params.nColMinEvents),:)=nan;
    % Create polygon with with slab-surface values x,y,z
end
delete(hMenuFig);

elseif strcmp(get(gcf,'name'),'3DResult plot')
    disp('here we go for a cross section');
    view(0,90);
    vSecLim1 = ginput(1)
    vSecLim2 = ginput(1)
    dist_=deg2km(distance(vSecLim1(2),vSecLim1(1),vSecLim2(2),vSecLim2(1)));
    azimuth_=azimuth(vSecLim1(2),vSecLim1(1),vSecLim2(2),vSecLim2(1));

    view(3);
end
for nLayer=1:length(params.vPercentiles);
    params.mPolygon(:,3)=params.mDepths(:,nLayer);
    % overgive depth values to the result-matrix
    params.mValueGrid(:,1)=params.mDepths(:,nLayer);

    for i=1:length(params.vY)
        params.mX(i,:)=params.vX;
    end
    for i=1:length(params.vX)
        params.mY(:,i)=params.vY;
    end

    params.mValueGrid(isnan(params.mPolygon(:,3)),:)=nan;

    % prepare 3D figure by reshaping
    params.mX=reshape(params.mX,length(params.vUsedNodes),1);
    params.mY=reshape(params.mY,length(params.vUsedNodes),1);
    params.mZ=ones(length(params.vUsedNodes),1)*nan;
    params.mZ(params.vUsedNodes)=params.mValueGrid(:,1);
    params.mX=reshape(params.mX,length(params.vY),length(params.vX));
    params.mY=reshape(params.mY,length(params.vY),length(params.vX));
    params.mZ=reshape(params.mZ,length(params.vY),length(params.vX));

    % transform spherical coordinates to xyz-coordinates
    % by applying distances-command

    % center of data as reference/origin point
    fOriginX_=(max(max(params.mX))+min(min(params.mX)))./2;
    fOriginY_=(max(max(params.mY))+min(min(params.mY)))./2;
    mOriginX_=ones(size(params.mX))*fOriginX_;
    mOriginY_=ones(size(params.mX))*fOriginY_;

    mYkm=deg2km(distance(params.mY,mOriginX_,mOriginY_,mOriginX_)).*sign(params.mY-mOriginY_);
    mXkm=deg2km(distance(mOriginY_,params.mX,mOriginY_,mOriginX_))*sin(deg2rad(fOriginY_)).*sign(params.mX-mOriginX_);

    % mZkm=ones(size(params.mZ))*50
    mZkm=params.mZ;

    % mZkm=ones(size(params.mZ))*50
    % mZkm(isnan(params.mZ))=nan
    % surfnorm(mXkm,mYkm,-mZkm);

    [mNxkm,mNykm,mNzkm]=surfnorm(mXkm,mYkm,-mZkm);

    % make figure
    % figure;
    % surf(params.mX,params.mY,-params.mZ);
    % surf(params.mX,params.mY,-params.mZ);
    % colorbar;
    % set(gca,'CLim',[0.6 1.4]);
    % box on
    % hold on; plot3(params.mPolygon(:,1),params.mPolygon(:,2),-params.mPolygon(:,3),'s','MarkerSize',5);
    [mNx,mNy,mNz]=surfnorm(params.mX,params.mY,-params.mZ);
    [mNxkm,mNykm,mNzkm]=surfnorm(mXkm,mYkm,-mZkm);
    % determin the gradient of the slab at each grid point
    [mGx,mGy]=gradient(params.mZ);
    [mGxkm,mGykm]=gradient(params.mZ);
    mGz=zeros(size(mGx,1),size(mGx,2));
    mGzkm=zeros(size(mGxkm,1),size(mGxkm,2));
    % take only valid gridpoints
    % mGx(isnan(mNx))=nan; mGy(isnan(mNx))=nan; mGz(isnan(mNx))=nan;

    vGx=reshape(mGx,size(mGx,1)*size(mGx,2),1);vGy=reshape(mGy,size(mGy,1)*size(mGy,2),1);vGz=reshape(mGz,size(mGz,1)*size(mGz,2),1);
    vNx=reshape(mNx,size(mNx,1)*size(mNx,2),1);vNy=reshape(mNy,size(mNy,1)*size(mNy,2),1);vNz=reshape(mNz,size(mNz,1)*size(mNz,2),1);
    % same for kmgrid
    vGxkm=reshape(mGxkm,size(mGxkm,1)*size(mGxkm,2),1);vGykm=reshape(mGykm,size(mGykm,1)*size(mGykm,2),1);vGzkm=reshape(mGzkm,size(mGzkm,1)*size(mGzkm,2),1);
    vNxkm=reshape(mNxkm,size(mNxkm,1)*size(mNxkm,2),1);vNykm=reshape(mNykm,size(mNykm,1)*size(mNykm,2),1);vNzkm=reshape(mNzkm,size(mNzkm,1)*size(mNzkm,2),1);

    mask=(~isnan(vGx) .* ~isnan(vGy) .* ~isnan(vGz) .* ~isnan(vNx) .* ~isnan(vNy) .* ~isnan(vNy));
    vGx(~mask)=nan;vGy(~mask)=nan;vGz(~mask)=nan;vNx(~mask)=nan;vNy(~mask)=nan;vNz(~mask)=nan;
    % same for km-grid
    mask=(~isnan(vGxkm) .* ~isnan(vGykm) .* ~isnan(vGzkm) .* ~isnan(vNxkm) .* ~isnan(vNykm) .* ~isnan(vNykm));
    vGxkm(~mask)=nan;vGykm(~mask)=nan;vGzkm(~mask)=nan;vNxkm(~mask)=nan;vNykm(~mask)=nan;vNzkm(~mask)=nan;
    % create a vector perpendicular to the surface define by the normal and the
    % gradient, mT is tangent and represents the axes of the sampling cylinder.
    params.mT=cross([vGx vGy vGz],[vNx vNy vNz]);
    % same for km-grid
    mTkm=cross([vGxkm vGykm vGzkm],[vNxkm vNykm vNzkm]);
%     hold on;quiver3(mXkm(:),mYkm(:),-mZkm(:),mTkm(:,1),mTkm(:,2),mTkm(:,3),2,'r');
    % hold on;quiver3(params.mX(:),params.mY(:),-params.mZ(:),params.mT(:,1),params.mT(:,2),params.mT(:,3),2,'r');
    % params.mT=params.mT(params.vUsedNodes,:)

    % we only want to have horizontal cylinder axis
    params.mT(~isnan(params.mT(:,3)),3)=0;

    for ii=1:length(Name)
        if strcmp(Name(ii),'Cylindrical Volume Sampling')
            disp(Name(ii));
            params.sComment=strcat(Name(ii),' Depth=',num2str(params.vPercentiles(nLayer)));
            [params.caNodeIndices2 params.vResolution2]=ex_CreateIndexCatalogCylinder(params.mCatalog,params.mPolygon,params.mT,...
                params.vUsedNodes,params.bCylSmpModeN,params.fCylSmpValue,params.fCylSmpBnd);
            if ((params.bCylSmpModeN==1) && (params.bCylSmpModeR==0))
                params.vcsGridNames(6) = cellstr(char('Resolution [R]'));
            else
                params.vcsGridNames(6) = cellstr(char('Resolution [N]'));
            end
        elseif strcmp(Name(ii),'3D Spherical Volume Sampling')
            disp(Name(ii));
            params.sComment=strcat(Name(ii),' Depth=',num2str(params.vPercentiles(nLayer)));
            % nGriddingMode = 3 means 3D sphere around polygonpoint
            params.nGriddingMode=3;
            % select
            % Create Indices to catalog and select quakes in time period
            [params.caNodeIndices2 params.vResolution2] = ex_CreateIndexCatalog3D(params.mCatalog, params.mPolygon, '1', params.n3DGriddingMode, ...
                params.f3DSmpValue, params.f3DSmpBnd, params.fSizeRectHorizontal, params.fSizeRectDepth);
            if ((params.b3DSmpModeN==1) && (params.b3DSmpModeR==0))
                params.vcsGridNames(6) = cellstr(char('Resolution [R]'));
            else
                params.vcsGridNames(6) = cellstr(char('Resolution [N]'));
            end
            % clear indices where not enough quakes for depth estimation
            for i=1:length(params.mPolygon)
                if isnan(params.mPolygon(i,3))
                    params.caNodeIndices2{i}=[];
                end
            end
        else
            disp('Something is going wrong');
        end

        % Calculation of bValue
        for i=1:length(params.mPolygon)
            if ~isempty(params.mCatalog(params.caNodeIndices2{i},:))
                % function [fBValue, fStdDev, fAValue, fMeanMag] =  calc_bvalue(mCatalog, fBinning)
                [params.mValueGrid(i,2),params.mValueGrid(i,3),params.mValueGrid(i,4),params.mValueGrid(i,5),] =  calc_bvalue(params.mCatalog(params.caNodeIndices2{i},:));
                params.mValueGrid(i,6)=max(params.vResolution2{i});
            else
                % create NaN's in mValueGrid, where strike is not defined
                params.mValueGrid(i,:)=nan;
            end

        end

        params.vcsGridNames(1:5) = cellstr(char(...
            'Depth Level',...               %   1
            'b-Value',...                   %   2
            'Standard Deviation',...        %   3
            'A-Value',...                   %   4
            'Mean Magnitude'));             %   5

        params.bMap=2;
        params.mValueGrid(isnan(params.mValueGrid(:,1)),:)=nan;
        vResults((nLayer-1)*length(Name)+ii)=params;

    end
end
save vResults
gui_result2(vResults);
disp('surf done');

% % plot the gradient on the slab
% hold on;quiver3(params.mX(:),params.mY(:),-params.mZ(:),mGx(:),mGy(:),0,2);
% % plot strike
% hold on;quiver3(params.mX(:),params.mY(:),-params.mZ(:),params.mT(:,1),params.mT(:,2),params.mT(:,3),3,'r');

% prepare Value that will be illustrated on the 3D surface defined above
% params.mC=ones(length(params.vUsedNodes),1)*nan;
% params.mC(params.vUsedNodes)=params.mValueGrid(:,2);
% params.mC(params.mC == 0)=nan;
% params.mC=reshape(params.mC,length(params.vY),length(params.vX));
% params.mZ(isnan(params.mC))=nan;

% make figure
% figure;
% surf(params.mX,params.mY,-params.mZ);
% surf(params.mX,params.mY,-params.mZ,params.mC);
% colorbar;
% set(gca,'CLim',[0.6 1.4]);
% box on
% shading interp


function [ Temp,WVapour,Geopot,Pressure,longrid,latgrid,xx,yy,lon0360_flag] = aps_load_merra(file,merra_model,coeff)
% loading merra data and output the variables for TRAIN
%
%     Copyright (C) 2016  Bekaert David
%     davidbekaert.com
%
%     This program is free software; you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation; either version 2 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License along
%     with this program; if not, write to the Free Software Foundation, Inc.,
%     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%
% modifications
% DB    10/04/2016      Base this code on aps_load_era.m modular approach
% DB    01/05/2016      Include MERRA2 support
% DB    12/11/2017      Change MERRA to be nc4

% debug figure to test and validate dataloading.
debug_fig = 0;

% missing values in the hdf files of MERRA
missing_value = 999999986991104;

% specify the coeficients in case they are not given
if nargin<3
    coeff.Rv= 461.495;           % [j/kg/K] water vapour
    coeff.Rd= 287.05;            % [j/kg/K] specific gas constants dry air
end
if ~isfield(coeff,'Rd') || ~isfield(coeff,'Rv')
   error('Coefficients Rd and Rv are not spcified')
end

%%
if strcmpi(merra_model,'merra')

    [a,b,file_ext] = fileparts(file);

    if strcmpi(file_ext,'.nc4')
        % open the netcdf
        ncid = netcdf.open(file,'NC_NOWRITE');

        % read netcdf variables and get number of variables
        [numdims,numvars,numglobalatts,unlimdimid] = netcdf.inq(ncid);

         % loading all the variables from the netcdf
         for i = 0:numvars-1
            [varname, xtype, dimids, numatts] = netcdf.inqVar(ncid,i);
            flag = 0;
            for j = 0:numatts - 1
                attname1 = netcdf.inqAttName(ncid,i,j);
                attname2 = netcdf.getAtt(ncid,i,attname1);

                if strcmp('add_offset',attname1)
                    offset = attname2;
                end

                if strcmp('scale_factor',attname1)
                    scale = attname2;
                    flag = 1;
                end
            end
            if flag
                eval([varname '= double(netcdf.getVar(ncid,i))*scale + offset;']);
            else
                eval([varname '= double(netcdf.getVar(ncid,i));']);
            end
            clear varname xtype dimids numatts scale offset
         end

         % close nedtcdf
        netcdf.close(ncid)

        % definition of QV
        qv = QV;

        % definition of geopotential
        % Convert Geopotential Height to geopotential
        % important this is needed to be consitent with the other weather modules
        g0 = 9.80665;
        Geopot = H.*g0;

        % define geocoordinates
        lons = XDim;
        lats = YDim;
        clear XDim YDim
        % define temperature
        Temp = T;
        clear T
        % define pressure
        Plevs = Height;
        clear Height

        % this is the time-stamps
        TIME./60;

    elseif  strcmpi(file_ext,'.hdf')
        %% OLD HDF5 files, seems no longer to work for new MERRA website
        % keep it for being backward compatible with earlier TRAIN version
        hdf_file = hdfinfo(file);
        Temp = hdfread(file,'/t');                      % temperature in [K]
        qv  = hdfread(file,'/qv');                      % specific humidity
        H =  hdfread(file,'/h');
        % Convert Geopotential Height to geopotential
        % important this is needed to be consitent with the other weather modules
        g0 = 9.80665;
        Geopot = H.*g0;                                 % geopotential
        Psurface = hdfread(file,'/ps');                 % surface pressure in [hPa]
        Plevs = hdfread(file,'/levels')';               % Pressure in [hPa]
        lons = hdfread(file,'/longitude')';
        lats = hdfread(file,'/latitude')';
    end
elseif strcmpi(merra_model,'merra2')

    % open the netcdf
    ncid = netcdf.open(file,'NC_NOWRITE');

    % read netcdf variables and get number of variables
    [numdims,numvars,numglobalatts,unlimdimid] = netcdf.inq(ncid);

     % loading all the variables from the netcdf
     for i = 0:numvars-1
        [varname, xtype, dimids, numatts] = netcdf.inqVar(ncid,i);
        flag = 0;
        for j = 0:numatts - 1
            attname1 = netcdf.inqAttName(ncid,i,j);
            attname2 = netcdf.getAtt(ncid,i,attname1);

            if strcmp('add_offset',attname1)
                offset = attname2;
            end

            if strcmp('scale_factor',attname1)
                scale = attname2;
                flag = 1;
            end
        end
        if flag
            eval([varname '= double(netcdf.getVar(ncid,i))*scale + offset;']);
        else
            eval([varname '= double(netcdf.getVar(ncid,i));']);
        end
        clear varname xtype dimids numatts scale offset
     end

     % close nedtcdf
    netcdf.close(ncid)

    % definition of QV
    qv = QV;

    % definition of geopotential
    % Convert Geopotential Height to geopotential
    % important this is needed to be consitent with the other weather modules
    g0 = 9.80665;
    Geopot = H.*g0;

    % define geocoordinates
    lons = lon;
    lats = lat;
    clear lon lat
    % define temperature
    Temp = T;
    clear T
    % define pressure
    Plevs = lev;
    clear lev

    % this is the time-stamps
    time./60;
end
%%
% update the no data values with NaN's
Temp(Temp==missing_value)=NaN;
qv(qv==missing_value)=NaN;
Geopot(Geopot==missing_value)=NaN;

% number of lon lat grid nodes
n_latitude_points = size(lats,1);
n_longitude_points = size(lons,1);

% generate the pressure levels
Pressure = repmat(Plevs,[1,n_latitude_points,n_longitude_points]);
Pressure = permute(Pressure,[2,3,1]);

% change the order of variables such its consistent with the pressure levels
if strcmpi(merra_model,'merra2')
    Temp = permute(Temp,[2,1,3]);
    qv = permute(qv,[2,1,3]);
    Geopot = permute(Geopot,[2,1,3]);

elseif  strcmpi(merra_model,'merra')
    if strcmpi(file_ext,'.nc4')
        Temp = permute(Temp,[2,1,3]);
        qv = permute(qv,[2,1,3]);
        Geopot = permute(Geopot,[2,1,3]);
    elseif strcmpi(file_ext,'.hdf')
        Temp = permute(Temp,[2,3,1]);
        qv =  permute(qv,[2,3,1]);
        Geopot = permute(Geopot,[2,3,1]);
    end
end

% computation of the saturated water vapour e
% use mixing ratio r = E*e/(p-e), where E = Rd/Rv
% and specific humidity qv = r/(1+r)
E = coeff.Rd./coeff.Rv;
WVapour= qv.*Pressure./(E.*(1-qv)+qv);
clear qv

% Get list of points to look at in analysis
[xx,yy] = meshgrid(1:n_longitude_points,1:n_latitude_points);

% generate the lon lat grid
latgrid = repmat(lats,[1,length(Plevs),n_longitude_points]);
latgrid = permute(latgrid,[1,3,2]);
longrid = repmat(lons,[1,length(Plevs),n_latitude_points]);
longrid = permute(longrid,[3,1,2]);

% inform about the organisation of the longitudes
if sum(lons>180)>1
    lon0360_flag = 'y';
else
    lon0360_flag = 'n';
end

% validation plots
if debug_fig ==1
    figure('position',[ 3         628        1402         586]);
    subplot(2,5,1)
    imagesc(Temp(:,:,end))
    colorbar
    axis xy
    axis equal
    axis tight
    title('temp upper atmo')
    subplot(2,5,2)
    imagesc(Temp(:,:,1))
    colorbar
    axis xy
    axis equal
    axis tight
    title('temp lower atmo')

    subplot(2,5,3)
    imagesc(Pressure(:,:,end))
    colorbar
    axis xy
    axis equal
    axis tight
    title('pressure upper atmo')
    subplot(2,5,4)
    imagesc(Pressure(:,:,1))
    colorbar
    axis xy
    axis equal
    axis tight
    title('pressure lower atmo')

    subplot(2,5,6)
    imagesc(WVapour(:,:,end))
    colorbar
    axis xy
    axis equal
    axis tight
    title('water vapour upper atmo')
    subplot(2,5,7)
    imagesc(WVapour(:,:,1))
    colorbar
    axis xy
    axis equal
    axis tight
    title('water vapour lower atmo')

    subplot(2,5,8)
    imagesc(Geopot(:,:,end))
    colorbar
    axis xy
    axis equal
    axis tight
    title('geopotential upper atmo')
    subplot(2,5,9)
    imagesc(Geopot(:,:,1))
    colorbar
    axis xy
    axis equal
    axis tight
    title('geopotential lower atmo')

    subplot(2,5,5)
    imagesc(latgrid(:,:,1))
    colorbar
    axis xy
    axis equal
    axis tight
    title('lat')
    subplot(2,5,10)
    imagesc(longrid(:,:,1))
    colorbar
    axis xy
    axis equal
    axis tight
    title('lon')
end

%
%
%
%  ncid = netcdf.open(file,'NC_NOWRITE');
% [numdims,numvars,numglobalatts,unlimdimid] = netcdf.inq(ncid);
% [dimname, dimlen] = netcdf.inqDim(ncid,0);
%
%         for k=1:numvars
%             [dimname, dimlen] = netcdf.inqVar(ncid,k-1);
%             fprintf([num2str(k-1) ' - ' dimname '\n'])
%         end


function [mriCoord] = cs_mni2mri(MRI,mniCoord)
% CS_MNI2MRI: Transform MNI point coordinates (in mm) to MRI coordinate system (in mm)
%
% DEPRECATED: Replace with cs_convert()

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

disp('BST> WARNING: Deprecated function cs_mni2mri(), use cs_convert() instead.');

mriCoord = cs_convert(MRI, 'mni', 'mri', mniCoord' / 1000)' * 1000;


function [mn cr]=finminexceptTabu(tmp,Tabu)
%% Written by Muhammet Balcilar, France
% all rights reverved
nodes=tmp(:,1:end-1);
cost=tmp(:,end);
for i=1:size(Tabu,1)
    tt=sum(abs(nodes-Tabu(i,:)),2);
    I=find(tt==0);
    if length(I)>0
        cost(I(1))=inf;
    end
end
[mn cr]=min(cost);


function [state, xf] = ft_preproc_online_filter_apply(state, x)

% FT_PREPROC_ONLINE_FILTER_APPLY passes a signal through the online filter and
% returns the updated filter model (delay states) and the filtered signal.
%
% Use as
%   [state, dat] = ft_preproc_online_filter_apply(state, dat)
% where
%   dat   = Nchan x Ntime
%   state = filter state, see FT_PREPROC_ONLINE_FILTER_INIT
%
% See also PREPROC

% Copyright (C) 2010, Stefan Klanke
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% 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$

[dimX, numX] = size(x);

if dimX > numX
  % explicit algorithm - faster for many channels, 1 sample (=fMRI)
  xf = zeros(size(x));

  for k=1:numX;
    z_old = state.z;
    z0 = x(:,k) - z_old*state.A2;
    xf(:,k) = z_old * state.B2 + z0*state.B1;
    state.z(:,2:end) = z_old(:,1:end-1);
    state.z(:,1) = z0;
  end
else
  % use built-in MATLAB stuff - faster for many samples, few channels
  [xf, z] = filter(state.B, state.A, x, state.z',2);
  state.z = z';
end


function T67=T67(h)

T67=-1.96e-3*h+373.2;


function At = ctranspose(A)
At.func = A.transpose;
At.transpose = A.func;
At = class(At,'A_operator');


function ind = VOChash_lookup_HH(hash,s)

hsize=numel(hash.key);
h=mod(str2double(s([5:7 9:end])),hsize)+1;
ind=hash.val{h}(strmatch(s,hash.key{h},'exact'));


% Script to create two drees files from ddbs stucture.
%1st file consists of all trials.
%2nd file consists of expected dvhs and the confidence bounds for the expeced dvhs.

fileName1 = '';
filename2 = '';

%File containing all DVHs
ddbsOriginal = ddbs;
numOriginalPatients = length(ddbs);
for iPat = 1:numOriginalPatients
    for iTrial = 1:length(ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.allTrials)
        dvh_tmp = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.allTrials{iTrial};
        ddbs(end+1) = ddbs(iPat);
        ddbs(end).dvh_Rectum_shift_0pt25cm = dvh_tmp;
    end
end

ddbs(1:numOriginalPatients) = [];
ddbs = rmfield(ddbs,'dvh_Rectum_shift_0pt25cm_rectum');
save(fileName1,'ddbs');

%File containing expected DVHs and the confidence bounds
ddbs = ddbsOriginal;
numOriginalPatients = length(ddbs);
for iPat = 1:numOriginalPatients
    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Expected = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.meanM;

    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Minus1Sigma = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.Minus1SigmaM;
    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Minus2Sigma = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.Minus2SigmaM;
    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Minus3Sigma = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.Minus3SigmaM;

    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Plus1Sigma = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.Plus1SigmaM;
    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Plus2Sigma = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.Plus2SigmaM;
    ddbs(iPat).dvh_Rectum_shift_0pt25cm_Plus3Sigma = ddbs(iPat).dvh_Rectum_shift_0pt25cm_rectum.Plus3SigmaM;
end

ddbs(1:numOriginalPatients) = [];
ddbs = rmfield(ddbs,'dvh_Rectum_shift_0pt25cm_rectum');
save(fileName2,'ddbs');


function [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx)

% READ_NEXSTIM_NXE reads specified samples from a NXE continous datafile
%
% Use as
%   [hdr] = read_nexstim_nxe(filename)
% where
%    filename        name of the datafile, including the .bdf extension
% This returns a header structure with the following elements
%   hdr.Fs           sampling frequency
%   hdr.nChans       number of channels
%   hdr.nSamples     number of samples per trial
%   hdr.nSamplesPre  number of pre-trigger samples in each trial
%   hdr.nTrials      number of trials
%   hdr.label        cell-array with labels of each channel
%
% Or use as
%   [dat] = read_nexstim_nxe(filename, begsample, endsample, chanindx)
% where
%    filename        name of the datafile, including the .nxe extension
%    begsample       index of the first sample to read
%    endsample       index of the last sample to read
%    chanindx        index of channels to read (optional, default is all)
% This returns a Nchans X Nsamples data matrix

% Written by Vladimir Litvak based on functions provided by Nexstim
%
% Copyright (C) 2007, Vladimir Litvak
%
% 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_nexstim_nxe.m 945 2010-04-21 17:41:20Z roboos $

if nargin==1
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % read the header
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    hdr.Fs          = 1450;
    hdr.nChans      = 64;
    hdr.label  = cell(64,1);
    hdr.label(1:4)= {'GATE', 'TRIG1', 'TRIG2','EOG'};
    hdr.label(5:64) = {
        'Fp1'
        'Fpz'
        'Fp2'
        'AF1'
        'AFz'
        'AF2'
        'F7'
        'F3'
        'F1'
        'Fz'
        'F2'
        'F4'
        'F8'
        'FT9'
        'FT7'
        'FC5'
        'FC3'
        'FC1'
        'FCz'
        'FC2'
        'FC4'
        'FC6'
        'FT8'
        'FT10'
        'T7'
        'C5'
        'C3'
        'C1'
        'Cz'
        'C2'
        'C4'
        'C6'
        'T8'
        'TP9'
        'TP7'
        'CP5'
        'CP3'
        'CP1'
        'CPz'
        'CP2'
        'CP4'
        'CP6'
        'TP8'
        'TP10'
        'P9'
        'P7'
        'P3'
        'P1'
        'Pz'
        'P2'
        'P4'
        'P8'
        'P10'
        'PO3'
        'POz'
        'PO4'
        'O1'
        'Oz'
        'O2'
        'Iz'};

    % it is continuous data, therefore append all records in one trial
    hdr.nTrials     = 1;

    fid=fopen(filename,'r','l');
    fseek(fid,0,'eof');
    numBytes = ftell(fid);
    hdr.nSamples = (numBytes/2)/hdr.nChans;

    hdr.nSamplesPre = 0;

    fclose(fid);

    % return the header
    dat = hdr;

else
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % read the data
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    sfEEG = (1/2000) * (10/65535) * 1000000;
    sfEOG = (1/400) * (10/65535) * 1000000;
    sfTRIG = 10 * (10/65535);

    numChannels = 64;

    fid = fopen(filename,'r','l');
    fseek(fid, 2*numChannels*(begsample-1),'bof');
    data = fread(fid,[numChannels endsample-begsample+1],'short');
    fclose(fid);

    data(1:3,:) = sfTRIG.*data(1:3,:);
    data(4,:) = sfEOG.*data(4,:);
    data(5:64,:) = sfEEG.*data(5:64,:);

    if nargin<4
        chanindx = 1:numChannels;
    end

    dat = data(chanindx,:);
end


function dX = apply_recursive_differentiation(model,x,requested,recursivederivativeprecompute)

global newmodel
persistent dX0
persistent index
persistent mtT
persistent monomTablePattern
persistent ss
persistent lastrequested

% Compute all evaluation-based derivatives df(x)
dxi = [];
dxj = [];
dxs = [];
for i = 1:length(model.evaluation_scheme)
    if strcmp(model.evaluation_scheme{i}.group,'eval')
        for j = model.evaluation_scheme{i}.variables
            if any(requested(model.evalMap{j}.computes))
                k = model.evalMap{j}.variableIndex;
                derivative = model.evalMap{j}.properties.derivative(x(k));
                z{i,j} = derivative;
                if i == 1
                    dxj = [dxj model.evalMap{j}.variableIndex];
                    if length(derivative)>1 && length(model.evalMap{j}.computes)==1
                        dxi = [dxi repmat(model.evalMap{j}.computes,1,length(derivative))];
                    else
                        dxi = [dxi model.evalMap{j}.computes];
                    end
                    dxs = [dxs;derivative(:)];
                end
            end
        end
    end
end

% Apply chain-rule. This code is horrible

if newmodel || ~isequal(requested,lastrequested);
    % Some precalc save over iterations
    ss = any(model.deppattern(requested,model.linearindicies),1);
    monomTablePattern = logical(model.monomtable);
    mtT = model.monomtable';
    [~,dxj] = ismember(dxj,model.linearindicies);
    dxi1 = [dxi model.linearindicies];
    dxj1 = [dxj 1:length(model.linearindicies)];
    dxs1 = [dxs(:)' ones(length(model.linearindicies),1)'];
    dX = sparse(dxi1,dxj1,dxs1,length(model.c),length(model.linearindicies));
    dX0 = dX;
    index = sub2ind([length(model.c),length(model.linearindicies)],dxi,dxj);
    newmodel = 0;
    lastrequested = requested;
else
    dX = dX0;
    dX(index) = dxs;
end

for i = 1:length(model.evaluation_scheme)
	group = model.evaluation_scheme{i}.group;
	if strcmp(group, 'eval')
		if i>1
			for variable = find(ss)
				for j = recursivederivativeprecompute{variable,i}
					 k = model.evalMap{j}.variableIndex;
					 if length(model.evalMap{j}.computes) == 1
						  dX(model.evalMap{j}.computes,variable) = dX(k,variable)'*z{i,j};
					 else
					  val = dX(k,variable).*z{i,j};
					  [idx,~,vdx] = find(val);
					  if ~isempty(vdx)
							dX(model.evalMap{j}.computes(idx),variable) = vdx;
					  end
					 end
				end
			end
		end
	elseif strcmp(group, 'monom')
		computed = model.monomials(model.evaluation_scheme{i}.variables);

		% quadratic and bilinear expressions in the bottom layer of
		% the computational tree can be differentiated very easily
		if i == 1
			 BilinearIndex = find(model.variabletype(computed)==1);
			 Bilinears = computed(BilinearIndex);
			 if ~isempty(Bilinears)
				  x1 = model.BilinearsList(Bilinears,1);
				  x2 = model.BilinearsList(Bilinears,2);
				  [~,x1loc] = ismember(x1,model.linearindicies);
				  [~,x2loc] = ismember(x2,model.linearindicies);
				  dX(sub2ind(size(dX),[Bilinears(:);Bilinears(:)],[x1loc;x2loc]))=x([x2;x1]);
			 end
			 QuadraticIndex = find(model.variabletype(computed)==2);
			 Quadratics = computed(QuadraticIndex);
			 if ~isempty(Quadratics)
				  x1 =  model.QuadraticsList(Quadratics,1);
				  [~,x1loc] = ismember(x1,model.linearindicies);
				  dX(sub2ind(size(dX),Quadratics',x1loc))=2*x(x1);
			 end
			 computed([BilinearIndex QuadraticIndex])=[];
		end

		if i > 1
			 % We might have inner derivatives from earlier
			 isBilinear = model.variabletype==1;
			 if all(isBilinear(computed))
				  % Special case quicker. Only bilinear monomials
				  b1 = model.BilinearsList(computed,1);
				  b2 = model.BilinearsList(computed,2);
				  dp = repmat(x(b2),1,length(model.linearindicies)).*dX(b1,:)+repmat(x(b1),1,length(model.linearindicies)).*dX(b2,:);
				  dX(computed,:) = dp;
			 else
				  compMTP = monomTablePattern(computed,:);
				  for variable = find(ss)
						[dXRows,~,dXVals] = find(dX(:,variable));
						hh = any(compMTP(:,dXRows),2);
						compInd = computed(hh);
						newIndices = compInd(requested(compInd)); % all values for loop
						% Create a working copy of dX(:,variable). Real size isn't
						% length(dXRows)+length(newIndices) but length(unique([dXRows;newIndices']).
						% But it's more efficient to allocate some more memory than calculate the true length.
						dx = sparse(dXRows,1,dXVals, size(dX,1),1, length(dXRows)+length(newIndices));
						for j = newIndices(:)'
							if isBilinear(j)
								 b1 = model.BilinearsList(j,1);
								 b2 = model.BilinearsList(j,2);
								 dp = x(b2)*full(dx(b1))+x(b1)*full(dx(b2));
							else
								 dp = 0;
								 monomsj = mtT(:,j);
								 active = find(monomsj & dx);
								 for k = active(:)'
									monoms = monomsj;
									[s,~,v] = find(monoms);
									k2s = s==k;
									r = v(k2s);
									v(k2s) = r-1;
									ztemp = prod(x(s).^v);
									aux = full(dx(k));
									dp = dp + r*aux*ztemp;
								 end
							end
							dx(j) = real(dp);
						end
						dX(:,variable) = dx(:);
				  end
			 end
		else
			% We are at the bottom layer, so no inner derivatives
			compMTP = monomTablePattern(computed,:);
			for variable = find(ss)
				dx = dX(:,variable);
				fdX = find(dx); % logical(dx); for sparse-matrices, FIND is about as fast.
				hh = any(compMTP(:,fdX),2); %#ok<FNDSB>
				compInd = computed(hh);
				for j = compInd(requested(compInd))
					k = model.linearindicies(variable);
					monoms = mtT(:,j);

					[s,~,v] = find(monoms);
					k2s = s==k;
					r = v(k2s);
					v(k2s) = r-1;
					dp = r*prod(x(s).^v);
					dX(j,variable) = real(dp);
				end
			end
		end
	end
end
end


function mrmMakeMovie(id,rotBegin,rotEnd)
%
%
% Function to make a movie of brain rotating left to ventral view.  This
% should really be a more general function, but this is a start.
%
%   written by amr Jun 2010
%

if ~exist('id','var'), id = 500; end
if ~exist('rotBegin','var')
    mrmRotateCamera(id,'left')
    [rotBegin,zoom1] = mrmGetRotation(id);
end

if ~exist('rotEnd','var')
    mrmRotateCamera(id,'bottom')
    [rotEnd,zoom2] = mrmGetRotation(id);
end

%keyboard
% Set the background color
p.color=[0,0,0,1];
%p.color=[.3,.3,.3,1];

host = 'localhost';
%id = 174;
mrMesh(host, id, 'background', p);

% % rotate left to bottom
rotY = [rotBegin(2):-pi/128:rotEnd(2)];
rotZ = [rotBegin(3):pi/128:rotEnd(3)];
rotX = ones(1,length(rotY))*pi;

% rotate bottom to left
% rotY = [rotEnd(2):pi/64:rotBegin(2)];
% rotZ = [rotEnd(3):-pi/64:rotBegin(3)];
% rotX = ones(1,length(rotY))*pi;

n = length(rotX);
%pitch = linspace(.5*pi, 1.5*pi, n);
%pitch = -pi/2.5;
%zoom = 1;
movDir = '/biac3/wandell7/data/Words/Meshes/';
movFile = 'mrmRotateVentralToLeft.avi';

%mkdir('/tmp', 'mrmMovie');
clear M;
%for(ii=1:length(pitch))
f.filename = 'nosave';
for(ii=1:length(rotX))
    mrmRotateCamera(id, [rotX(ii) rotY(ii) rotZ(ii)], zoom1);

    [id,stat,res] = mrMesh(host, id, 'screenshot', f);
    M((1-1)*length(rotX)+ii) = im2frame(permute(res.rgb, [2,1,3])./255);

    %fname = sprintf('%c%0.2d.png', ltr(ii), jj);
    %fname = fullfile(movDir, fname);
    %imwrite(permute(res.rgb,[2,1,3])./255, fname);
end
%end
%figure; movie(M,-3)
movie2avi(M,fullfile(movDir,movFile)); %'/tmp/mrmMovieAllFrames.avi');

return

function [rot,zoom] = mrmGetRotation(id)
% Get rotation and zoom
p.actor=0; p.get_all=1;
[id,stat,r] = mrMesh('localhost', id, 'get', p);
zoom = diag(chol(r.rotation'*r.rotation))';
rotMat = r.rotation/diag(zoom);
% Note- there may be slight rounding errors allowing the inputs to
% asin/atan go outside of the range (-1,1). May want to clip those.
rot(2) = asin(rotMat(1,3));
if (abs(rot(2))-pi/2).^2 < 1e-9,
	rot(1) = 0;
	rot(3) = atan2(-rotMat(2,1), -rotMat(3,1)/rotMat(1,3));
else
	c      = cos(rot(2));
	rot(1) = atan2(rotMat(2,3)/c, rotMat(3,3)/c);
	rot(3) = atan2(rotMat(1,2)/c, rotMat(1,1)/c);
end
rot(1) = -rot(1); % flipped OpenGL Y-axis.
rot(3) = -rot(3);
fprintf('rot=[%0.6f %0.6f %0.6f];\nzoom=[%0.3f %0.3f %0.3f];\nfrustum=[%0.6f %0.6f %0.6f %0.6f];\n',rot,zoom,r.frustum);

return


function results = run_STRCF(seq, res_path, bSaveImage)

% Feature specific parameters
hog_params.cell_size = 4;
hog_params.compressed_dim = 10;
hog_params.nDim = 31;

grayscale_params.colorspace='gray';
grayscale_params.cell_size = 4;

cn_params.tablename = 'CNnorm';
cn_params.useForGray = false;
cn_params.cell_size = 4;
cn_params.nDim = 10;

% Which features to include
params.t_features = {
    struct('getFeature',@get_colorspace, 'fparams',grayscale_params),...
    struct('getFeature',@get_fhog,'fparams',hog_params),...
    struct('getFeature',@get_table_feature, 'fparams',cn_params),...
};

% Global feature parameters1s
params.t_global.cell_size = 4;                  % Feature cell size

% Image sample parameters
params.search_area_shape = 'square';    % The shape of the samples
params.search_area_scale = 5;         % The scaling of the target size to get the search area
params.min_image_sample_size = 150^2;   % Minimum area of image samples
params.max_image_sample_size = 200^2;   % Maximum area of image samples

% Spatial regularization window_parameters
params.feature_downsample_ratio = [4]; %  Feature downsample ratio
params.reg_window_max = 1e5;           % The maximum value of the regularization window
params.reg_window_min = 1e-3;           % the minimum value of the regularization window

% Detection parameters
params.refinement_iterations = 1;       % Number of iterations used to refine the resulting position in a frame
params.newton_iterations = 5;           % The number of Newton iterations used for optimizing the detection score
params.clamp_position = false;          % Clamp the target position to be inside the image

% Learning parameters
params.output_sigma_factor = 1/16;		% Label function sigma
params.temporal_regularization_factor = [15 15]; % The temporal regularization parameters

% ADMM parameters
params.max_iterations = [2 2];
params.init_penalty_factor = [1 1];
params.max_penalty_factor = [0.1, 0.1];
params.penalty_scale_step = [10, 10];

% Scale parameters for the translation model
% Only used if: params.use_scale_filter = false
params.number_of_scales = 5;            % Number of scales to run the detector
params.scale_step = 1.01;               % The scale factor

% Visualization
params.visualization = 1;               % Visualiza tracking and detection scores

% GPU
params.use_gpu = false;                 % Enable GPU or not
params.gpu_id = [];                     % Set the GPU id, or leave empty to use default

% Initialize
params.seq = seq;

% Run tracker
results = tracker(params);


function [ctcell,ct_xmesh,ct_ymesh,ct_zmesh] = dicomrt_loadct(filename,sorting)
% dicomrt_loadct(filename,sorting)
%
% Read dicom CT for a case using MATLAB native function dicomread. Light Version.
%
% filename contains a list of CT slices to import
%
% CT are stored in a single 3D matrix: case_study
% x-y-z coordinates of the center of the ct-pixel are stored in ct_xmesh, ct_ymesh and ct_zmesh.
%
% NOTE:  CT numbers range from -1000 for air to 1000 for bone with that for water set to 0.
% CT numbers normalized in this manner are called Hounfield numbers or units (HU):
%
% HU = ((mu_tissue-mu_water)/mu_water)*1000
%
% Following DICOM RT standard HU = m*(SV)+b where m is RescaleSlope, b RescaleIntercept
% and SV are pixel (stored) values.
%
% Often CT scale is shifted so that HU(water)=1000 (=CToffset) instead of 0.
%
% NOTE: as opposed to dicomrt_loadct ct_xmesh, ct_ymesh and ct_zmesh are vectors and not
% matrices. This allow to run this functions also in "low" memory pcs.
%
% See also dicomrt_loaddose, dicomrt_getPatientPosition
%
% Copyright (C) 2002 Emiliano Spezi (emiliano.spezi@physics.org)

% Sort CT slices first
%
% load ct slices info

% Check number of argument and set-up some parameters and variables
error(nargchk(1,2,nargin))

if exist('sorting')==0
    sorting=1; % perform sorting check
end

% Retrieve the number of images
nlines=dicomrt_nASCIIlines(filename);

if nlines>1
    disp('Loading CT slice information ...');
    [filelist,xlocation,ylocation,zlocation,modifUID,user_request] = dicomrt_loadctlist(filename);
    if user_request==1;
        return
    end
    disp('CT slice information loaded.');

    if sorting==1
        % sort ct slices
        disp('Sorting CT slices ...');
        [modifZ,user_request]=dicomrt_sortct(filelist,xlocation,ylocation,zlocation,filename);
        if user_request==1;
            return
        end
        disp('CT slices sorted.');
    else
        modifZ=0;
        modifUID=0;
    end

    if modifZ~=0 | modifUID~=0 % a modification to the filelist was made by dicomrt_sortct
        filename_sorted=[filename,'.sort.txt'];
    else % no modification have been made
        filename_sorted=filename;
    end
else
    disp('Loading one image. Zmesh will have no sense. Slice position can be loaded using dicominfo.');
    filename_sorted=filename;
end

% Now get CT images and create 3D Volume

% Set parameters
CToffset=1000;
nct=0;

% Define cell array to store info
case_study_info=cell(1);

%loop until the end-of-file is reached and build 3D CT matrix
disp('Loading ct volume ...');

% Progress bar
h = waitbar(0,['Loading progress:']);
set(h,'Name','dicomrt_loadct: loading CT images');

fid=fopen(filename_sorted);

while (feof(fid)~=1);
    clear info_temp temp
    nct=nct+1; % counting
    nctcheck=nct; % check for eof
    ct_file_location{1,nct}=fgetl(fid);
    if isnumeric(ct_file_location{1,nct}), nct=nct-1; break, end %end of line reached

    temp=dicomread(deblank(ct_file_location{1,nct}));

    dictFlg = checkDictUse;
    if dictFlg
        if isdeployed
            info_temp = dicominfo(deblank(ct_file_location{1,nct}),...
                'dictionary', fullfile(getCERRPath,'bin','ES - IPT4.1CompatibleDictionary.mat'));
        else
            info_temp = dicominfo(deblank(ct_file_location{1,nct}),...
                'dictionary', 'ES - IPT4.1CompatibleDictionary.mat');
        end
    else
        info_temp=dicominfo(deblank(ct_file_location{1,nct}));
    end

    zmesh(nct)=info_temp.ImagePositionPatient(3);

    if isfield(info_temp,'RescaleSlope')~=0 | isfield(info_temp,'RescaleIntercept')~=0
        temp=double(temp)*info_temp.RescaleSlope+info_temp.RescaleIntercept+CToffset;
    else
        warning('dicomrt_loadct: no DICOM Rescale data were found. Assuming RescaleSlope = 1, RescaleIntercept = 0 and CToffset = 1000');
        temp=double(temp);
    end

    case_study_info{nct}=info_temp;
    case_study(:,:,nct)=uint16(temp);
    waitbar(nct/nlines,h);
end

% Make zmesh a column vector
zmesh=dicomrt_makevertical(zmesh);

fclose(fid);

if nctcheck~=nct;
    warning('dicomrt_loadct: End of file was prematurely reached. Check the expected dimensions of your data. It may be OK to continue');
end

[PatientPositionCODE]=dicomrt_getPatientPosition(info_temp);

% PatientOrientation     ImageOrientationPatient
%
% HFS                    (1,0,0) (0,1,0)
% FFS                    (1,0,0) (0,1,0)
% HFP                    (-1,0,0) (0,-1,0)
% FFP                    (-1,0,0) (0,-1,0)
%
%
if PatientPositionCODE == 1 | PatientPositionCODE == 2
    min_x=info_temp.ImagePositionPatient(1);
    pixel_spacing_x=info_temp.PixelSpacing(1);

    min_y=info_temp.ImagePositionPatient(2);
    pixel_spacing_y=info_temp.PixelSpacing(2);

    [xmesh] = dicomrt_create1dmesh(min_x,pixel_spacing_x,size(temp,2),0);
    [ymesh] = dicomrt_create1dmesh(min_y,pixel_spacing_y,size(temp,1),0);

else
    max_x=info_temp.ImagePositionPatient(1);
    pixel_spacing_x=info_temp.PixelSpacing(1);

    max_y=info_temp.ImagePositionPatient(2);
    pixel_spacing_y=info_temp.PixelSpacing(2);

    [xmesh] = dicomrt_create1dmesh(max_x,pixel_spacing_x,size(temp,1),1);
    [ymesh] = dicomrt_create1dmesh(max_y,pixel_spacing_y,size(temp,2),1);

end

ct_zmesh=dicomrt_mmdigit(zmesh*0.1,7);
ct_ymesh=dicomrt_mmdigit(ymesh*0.1,7);
ct_xmesh=dicomrt_mmdigit(xmesh*0.1,7);

disp('Loading complete ...');

% 3D CT matrix and mesh matrix imported
%
% Some CT images info have private tags or fragmented info.
% If so, go into manual mode.
%

% Check support for current Patient Position
if PatientPositionCODE == 1 % supported Patient Position: HFS
    disp('dicomrt_loadct: Patient Position is Head First Supine (HFS).');
elseif PatientPositionCODE == 2 % supported Patient Position: FFS
    disp('dicomrt_loadct: Patient Position is Feet First Supine (FFS).');
elseif PatientPositionCODE == 3 % unsupported Patient Position: HFP
    disp('dicomrt_loadct: Patient Position is Head First Prone (HFP).');
elseif PatientPositionCODE == 4 % unsupported Patient Position: FFP
    disp('dicomrt_loadct: Patient Position is Feet First Prone (FFP).');
else
    warning('Unable to determine Patient Position');
    PatientPosition=input('dicomrt_loadct: Please specify Patient Position: HFS(default),FFS,HFP,FFP: ','s');
    if isempty(PatientPosition)==1
        PatientPosition='HFS';
    end

    if strcmpi(PatientPosition, 'HFS')
        PatientPositionCODE = 1;
    elseif strcmpi(PatientPosition, 'FFS')
        PatientPositionCODE = 2;
    elseif strcmpi(PatientPosition, 'HFP')
        PatientPositionCODE = 3;
    elseif strcmpi(PatientPosition, 'FFP')
        PatientPositionCODE = 4;
    end

end

% Create cell array
ctcell=cell(3,1);
ctcell{1,1}=case_study_info;
ctcell{2,1}=case_study;
ctcell{3,1}=[];

% Close progress bar
close(h);
pack


function mask = mri_fillholes(mask, dim)
% MRI_FILLHOLES: Detect background, then fill everything that is not background

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

% Initialize two accumulators, for the two directions
acc1 = false(size(mask));
acc2 = false(size(mask));
n = size(mask,dim);
% Process in required direction
switch dim
    case 1
        for i = 2:n
            acc1(i,:,:) = acc1(i-1,:,:) | mask(i,:,:);
        end
        for i = n-1:-1:1
            acc2(i,:,:) = acc2(i+1,:,:) | mask(i,:,:);
        end
    case 2
        for i = 2:n
            acc1(:,i,:) = acc1(:,i-1,:) | mask(:,i,:);
        end
        for i = n-1:-1:1
            acc2(:,i,:) = acc2(:,i+1,:) | mask(:,i,:);
        end
    case 3
        for i = 2:n
            acc1(:,:,i) = acc1(:,:,i-1) | mask(:,:,i);
        end
        for i = n-1:-1:1
            acc2(:,:,i) = acc2(:,:,i+1) | mask(:,:,i);
        end
end
% Combine two accumulators
mask = acc1 & acc2;


function [ s ] = geosubset_construct(starttime, stoptime, t_stride, zmin, zmax, z_stride, eastmin, ...
  eastmax, x_stride, northmin, northmax, y_stride)
% SUBSET_STRUCT this is a function that, in a matlab way, creates a subset structure for nctoolbox's
% geosubset or timegeosubset functions.
% >> geosubset_construct(1, 1, [], 1, 1, [], -77, -75.5, [],  36, 38, 1)
%
% Note: the starttime and stoptime arugments also accept matlab time formats datevec and datenum.
%

% Bounding Dimensions
s.lat = [northmin northmax]; % both ends must be explicit
s.lon = [eastmin eastmax]; % both ends must be explicit
s.z_index = [zmin zmax]; % both ends must be explicit
s.time = {starttime stoptime}; %both ends must be explicit

% Stride Arugments
if isempty(z_stride) % Z
  s.z_stride = 1;
else
  s.z_stride = z_stride;
end

if isempty(t_stride) % Time
  s.t_stride = 1;
else
  s.t_stride = t_stride;
end

if isempty(x_stride) %lon
  s.xy_stride(1) = 1;
else
  s.xy_stride(1) = x_stride;
end

if isempty(y_stride) %lat
  s.xy_stride(2) = 1;
else
  s.xy_stride(2) = y_stride;
end

end


function [n, ts_left, ts_right] = nex_int(filename, varname)
% nex_int(filename, varname): Read interval variable from a .nex file
%
% [n, ts_left, ts_right] = nex_int(filename, varname)
%
% INPUT:
%   filename - if empty string, will use File Open dialog
%   varname - variable name
% OUTPUT:
%   n - number of intervals
%   ts_left - array of left ends of the intervals (in seconds)
%   ts_right - array of right ends of the intervals (in seconds)

% original from Plexon, download from http://www.plexoninc.com (8/4/02)
% modifications by Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% 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$

n = 0;
ts_left = 0;
ts_right = 0;

if(nargin ~= 2)
   disp('2 input arguments are required')
   return
end

if(ischar(filename) == 0)
   disp('input arguments should be character arrays')
   return
end

if(ischar(varname) == 0)
   disp('input arguments should be character arrays')
   return
end

if(length(filename) == 0)
   [fname, pathname] = uigetfile('*.nex', 'Select a Nex file');
    filename = strcat(pathname, fname);
end

fid = fopen(filename, 'r', 'ieee-le');
if(fid == -1)
    disp('cannot open file');
   return
end

disp(strcat('file = ', filename));
magic = fread(fid, 1, 'int32');
version = fread(fid, 1, 'int32');
comment = fread(fid, 256, 'char');
freq = fread(fid, 1, 'double');
tbeg = fread(fid, 1, 'int32');
tend = fread(fid, 1, 'int32');
nvar = fread(fid, 1, 'int32');
fseek(fid, 260, 'cof');
name = zeros(1, 64);
found = 0;
for i=1:nvar
    type = fread(fid, 1, 'int32');
    var_version = fread(fid, 1, 'int32');
    name = fread(fid, [1 64], 'char');
    offset = fread(fid, 1, 'int32');
    n = fread(fid, 1, 'int32');
    name = char(name);
    name = deblank(name);
    k = strcmp(name, deblank(varname));
    if(k == 1)
        if type ~= 2
            disp(sprintf('%s is not an interval variable', deblank(varname)));
            return;
        end
        found = 1;
        fseek(fid, offset, 'bof');
        ts_left = fread(fid, [1 n], 'int32');
        ts_right = fread(fid, [1 n], 'int32');
        break
    end
    dummy = fread(fid, 128, 'char');
end

fclose(fid);

if found == 0
    disp('did not find variable in the file');
else
    ts_left = ts_left/freq;
    ts_right = ts_right/freq;
    disp(strcat('number of intervals = ', num2str(n)));
end


classdef TestInterpolateCornersCharuco
    %TestInterpolateCornersCharuco

    methods (Static)
        function test_1
            [img, board] = get_image_markers();
            [corners, ids] = cv.detectMarkers(img, board{end});
            [charucoCorners, charucoIds, num] = cv.interpolateCornersCharuco(...
                corners, ids, img, board);
            validateattributes(charucoCorners, {'cell'}, {'vector'});
            cellfun(@(c) validateattributes(c, {'numeric'}, ...
                {'vector', 'numel',2}), charucoCorners);
            validateattributes(charucoIds, {'numeric'}, ...
                {'vector', 'integer', 'nonnegative'});
            assert(isequal(numel(charucoCorners),numel(charucoIds)));
            validateattributes(num, {'numeric'}, ...
                {'scalar', 'integer', 'nonnegative'});
            assert(isequal(num,numel(charucoIds)));
        end

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

end

function [img, board] = get_image_markers()
    % markers in a 5x7 charuco board
    board = {5, 7, 60, 40, '6x6_50'};
    img = cv.drawCharucoBoard(board, [340 460], 'MarginSize',20);
    img = repmat(img, [1 1 3]);
end


function y = evaluate(this, x)
%EVALUATE   Evaluate robust function.
%   EVALUATE(THIS, X) evaluates the robust function THIS at point(s) X.
%
%   This is a member function of the class 'robust_function'.
%
%   Author:  Stefan Roth, Department of Computer Science, TU Darmstadt
%   Contact: sroth@cs.tu-darmstadt.de
%   $Date:  $
%   $Revision: $

% Copyright 2004-2007, Brown University, Providence, RI. USA
% Copyright 2007-2010 TU Darmstadt, Darmstadt, Germany.
%
%                          All Rights Reserved
%
% All commercial use of this software, whether direct or indirect, is
% strictly prohibited including, without limitation, incorporation into in
% a commercial product, use in a commercial service, or production of other
% artifacts for commercial purposes.
%
% Permission to use, copy, modify, and distribute this software and its
% documentation for research purposes is hereby granted without fee,
% provided that the above copyright notice appears in all copies and that
% both that copyright notice and this permission notice appear in
% supporting documentation, and that the name of the author and Brown
% University not be used in advertising or publicity pertaining to
% distribution of the software without specific, written prior permission.
%
% For commercial uses contact the Technology Venture Office of Brown University
%
% THE AUTHOR AND BROWN UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO
% THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
% FITNESS FOR ANY PARTICULAR PURPOSE.  IN NO EVENT SHALL THE AUTHOR OR
% BROWN UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
% DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
% PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
% ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
% THIS SOFTWARE.

  y = feval(this.type, x, this.param, 0);


function [ flag ed ] = edf(matr,eds,vexs,ed,tem)
flag = 1;
for i = 2:eds
    [dvex f]=flecvexf(matr,i,vexs,eds,ed,tem);
    if f==1;
        flag = 0;
        break;
    end
    if dvex ~= 0
        ed(:,i)=[vexs(1,i) dvex];
        vexs(1,i+1)=dvex;
        matr(vexs(1,i+1),vexs(1,i))=0;
    else
        break;
    end
end

end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%    gb 05/17/05
%
% This script has to be executed directly in the command line
% It computes the MSE and the MI for the current Inplane.
%
% For each data type, it tries to compute 3 errors:
%       - Total error (without ROI)
%       - Error with the ROIdef
%       - Error with the ROI associated with this data type
%
% If it does not find the ROI concerned, it skips to the next computation.
%
% example:
%
%   close all
%   clear all
%   mrVista
%   vw = getSelectedInplane;
%   computeError
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

global dataTYPES

for i = 1:length(dataTYPES)
    vw = viewSet(vw,'currentDataType',i);

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % The data Type 'Preprocessed' contains 468 frames in one scan (instead of 78)
    % The error cannot be calculated this way because of a lack of memory.
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if strcmp(dataTYPES(i).name(1:2),'Pr')
        continue
    end

    % Computes the total error
    motionCompPlotMSE(vw,'',0);
    motionCompPlotMI(vw,'',0);

    if i == 1
        % If the data type is Original, computes all the possible errors
        ROInames = dir(roiDir(vw));

        for j = 3:length(ROInames)
            ROIname = ROInames(j).name(1:end - 4);
            motionCompPlotMSE(vw,ROIname,0);
            motionCompPlotMI(vw,ROIname,0);
        end

    else
       % Computes the 2 other errors explained in the head comment
        if exist(fullfile(roiDir(vw),'ROIdef.mat'),'file')
			motionCompPlotMSE(vw,'ROIdef',0);
			motionCompPlotMI(vw,'ROIdef',0);
        end

        ROIname = ['ROI_' dataTYPES(i).name];

        if exist(fullfile(roiDir(vw),[ROIname '.mat']),'file')
            motionCompPlotMSE(vw,ROIname,0);
            motionCompPlotMI(vw,ROIname,0);
        end
    end

end


report_this_filefun(mfilename('fullpath'));

%l = isnan(tmap);
%tmap(l) = 1;

%l = tmap < 1;
%tmap(l) = 1;

[lat,lon] = meshgrat(tmap,tmapleg);
%[smap,smapleg] = country2mtx('switzerland',100);
%[lat0, lon0] = meshgrat(smap,smapleg);

% tmap = km2deg(tmap/1);
[X , Y]  = meshgrid(gx,gy);

%sw = interp2(lon0,lat0,smap,lon,lat);

%  re4 = re3;

l = re4 < -2.0;
re4(l) = -2.0;
l = re4 > 2.0;
re4(l) = 2.0;
re4 = re4+1200;

ren = interp2(X,Y,re4,lon,lat);

mi = min(min(ren));
l =  isnan(ren);
ren(l) = mi-20;

figure_w_normalized_uicontrolunits('pos',[150 500 1000 700])

hold on; axis off
axesm('MapProjection','eqaconic','MapParallels',[],...
    'MapLatLimit',[33.0 36.2],'MapLonLimit',[-118.1 -115.3])

meshm(ren,tmapleg,size(tmap),tmap);

daspectm('m',1.5);
tightmap
%view([10 30])
hl = camlight ; lighting phong
set(gca,'projection','perspective');

aa = a;

l = aa(:,6) > 1.5 & aa(:,3) < 1992.2;
a = aa.subset(l);
for i = 1:length(a)

    dep = interp2(lon,lat,tmap,a(i,1),a(i,2));

    pl =plot3m(a(i,2),a(i,1),dep+55,'or');
    hold on
    fac = 64/max(a.Depth);

    facm = 9/max(a.Magnitude);
    sm = aa(i,6)* facm;
    if sm < 1; sm = 1; end

    co = ceil(a(i,7)*fac)+1; if co > 63; co = 63; end
    set(pl,'Markersize',sm);
end

l = aa(:,6) > 1.5 & aa(:,3) > 1992.55;
a = aa.subset(l);
for i = 1:length(a)

    dep = interp2(lon,lat,tmap,a(i,1),a(i,2));

    pl =plot3m(a(i,2),a(i,1),dep+55,'^b');
    hold on
    fac = 64/max(a.Depth);

    facm = 9/max(a.Magnitude);
    sm = aa(i,6)* facm;
    if sm < 1; sm = 1; end

    co = ceil(a(i,7)*fac)+1; if co > 63; co = 63; end
    set(pl,'Markersize',sm);
end
cd /alaskah2/stefan/ZMAP/agu99
load hec.mat

for i = 1:length(a)
    dep = interp2(lon,lat,tmap,a(i,1),a(i,2));

    pl =plot3m(a(i,2),a(i,1),dep+55,'ok');
    hold on
    fac = 64/max(a.Depth);

    facm = 6/max(a.Magnitude);
    sm = a(i,6)* facm;
    if sm < 1; sm = 1; end

    co = ceil(a(i,7)*fac)+1; if co > 63; co = 63; end
    set(pl,'Markersize',sm,'markerfacecolor','y');
end

load land.mat

for i = 1:length(a)
    dep = interp2(lon,lat,tmap,a(i,1),a(i,2));

    pl =plot3m(a(i,2),a(i,1),dep+55,'sk');
    ;
    hold on
    fac = 64/max(a.Depth);

    facm = 6/max(a.Magnitude);
    sm = a(i,6)* facm;
    if sm < 1; sm = 1; end

    co = ceil(a(i,7)*fac)+1; if co > 63; co = 63; end
    set(pl,'Markersize',sm,'markerfacecolor','y');
end
load bb.mat

for i = 1:length(a)
    dep = interp2(lon,lat,tmap,a(i,1),a(i,2));

    pl =plot3m(a(i,2),a(i,1),dep+55,'sk');

    hold on
    fac = 64/max(a.Depth);

    facm = 6/max(a.Magnitude);
    sm = a(i,6)* facm;
    if sm < 1; sm = 1; end

    co = ceil(a(i,7)*fac)+1; if co > 63; co = 63; end
    set(pl,'Markersize',sm,'markerfacecolor','y');
end

for i = 1:length(maepi(:,3))
    pl =plotm(maepi(i,2),maepi(i,1),'hk');
    set(pl,'Markersize',18,'markerfacecolor','w');
end

plotm(faults(:,2), faults(:,1),'k','Linewidth',1.0);

zdatam(handlem('allline'),10000) % keep line on surface
j = jet;
%j = j(64:-1:1,:);
j = [ [ 0.85 0.9 0.9] ; j;  [ 0.85 0.9 0.9] ]
%caxis([ min(min(re4)) max(max(re4)) ]);

colormap(j); brighten(0.1);
caxis([-2.10 2.10]);
axis off; set(gcf,'color','k')

setm(gca,'ffacecolor','k')
setm(gca,'fedgecolor','w','flinewidth',3);

setm(gca,'mlabellocation',1)
setm(gca,'meridianlabel','on')
setm(gca,'plabellocation',1)
setm(gca,'parallellabel','on')
setm(gca,'Fontcolor','w','Fontweight','bold','FontSize',12,'Labelunits','dm')

set(gcf,'Inverthardcopy','off');

a = aa;


%{
 * Copyright (C) 2020-2030, The Regents of The University of Michigan.
 * All rights reserved.
 * This software was developed in the Biped Lab (https://www.biped.solutions/)
 * under the direction of Jessy Grizzle, grizzle@umich.edu. This software may
 * be available under alternative licensing terms; contact the address above.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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.
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Regents of The University of Michigan.
 *
 * AUTHOR: Bruce JK Huang (bjhuang[at]umich.edu)
 * WEBSITE: https://www.brucerobot.com/
%}

function [X_clean, clean_up, remaining_indices, edges] = cleanLiDARTargetWithOneDataSetWithIndices(X_original, target_len, opt)
    N = 4; % clean up using N std for x axis
    M = 3; % clean up using M std for y, z axis
    opt = optimizeCost(opt, X_original, target_len, 0.001);
    if size(X_original, 2) ~= 4
        X = [X_original(1:3, :);
             ones(1 ,size(X_original, 2))];
    end

    X_ref = opt.H_opt * X;
%     distance = sum(X_ref(1:3,:), 1); % L1
    L_infinity = max(abs(X_ref(1:3,:)));  % L infinity
    K = find(L_infinity < (target_len/2)*1.025);
    X_ref_clean_yz = X_ref(:, K); % clean up y and z axis
    L_infinity = max(X_ref_clean_yz(1:3,:));
    K_center = find(L_infinity < target_len/4);
    X_std = std(X_ref_clean_yz(:, K_center), 1, 2);
    Q = find(abs(X_ref(1,:)) < N*(X_std(1))); % clean up x with 2 std
    remaining_indices = intersect(K, Q);
    X_ref_clean = X_ref(:, remaining_indices);
    X_clean = inv(opt.H_opt) * X_ref_clean;
    clean_up.std = N*(X_std(1));
    clean_up.L_infinity = L_infinity;
    clean_up.L_1 = sum(X_ref(1:3,:), 1);
    X_ref_with_all_info = X_original;
    X_ref_with_all_info(1:3, :) = X_ref(1:3,:);
    edges = findEdgePointsInIdealFrame(opt.H_opt, X_ref_with_all_info, target_len);
%     figure(200);
%     clf('reset')
%     scatter3(X_ref(1,:), X_ref(2,:), X_ref(3,:))
%     xlabel('x')
%     ylabel('y')
%     zlabel('z')
%     axis equal
%     hold on;
% %     scatter3(X_ref_clean_yz(1,:), X_ref_clean_yz(2,:), X_ref_clean_yz(3,:))
%     scatter3(X_ref_clean(1,:), X_ref_clean(2,:), X_ref_clean(3,:))
%     axis equal
%     view(90,0)
%     hold off;
end


function varargout = atan(varargin)

switch class(varargin{1})

    case 'sdpvar'
        varargout{1} = InstantiateElementWise(mfilename,varargin{:});

    case 'char'

        operator = CreateBasicOperator('increasing','callback');
        operator.derivative = @(x)((1+x.^2).^-1);
        operator.inverse = @(x)(tan(x));
        operator.inflection = [-inf 1 0 -1];
        operator.range = [-pi/2 pi/2];

        varargout{1} = [];
        varargout{2} = operator;
        varargout{3} = varargin{3};

    otherwise
        error(['SDPVAR/' upper(mfilename) ' called with weird argument']);
end


function test_suite=SimTest_qmt_bssfp_test
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 TestSetup
setenv('ISDISPLAY','0') % go faster! Fit only 2 voxels in FitData.m
setenv('ISCITEST','1')

function test_Sim
disp('===========================================')
disp('Running simulation test for qmt_bssfp');
disp('testing Simulation Single Voxel Curve...');

Model = str2func('qmt_bssfp'); Model = Model();
savedModel_fname = fullfile(fileparts(which('qMRLab')),'Test','MoxUnitCompatible','static_savedModelsforRetrocompatibility',['qmt_bssfp.qmrlab.mat']);
if ~exist(savedModel_fname,'file')
Model.saveObj(savedModel_fname);
else
Model = Model.loadObj(savedModel_fname);
end

disp(class(Model))
try Opt = button2opts(Model.Sim_Single_Voxel_Curve_buttons,1); end
try st = Model.st; catch, try st = mean([Model.lb(:),Model.ub(:)],2); catch, st = ones(length(Model.xnames),1); end; end
if exist('Opt','var') && length(Opt)>1
[Opt(:).SNR] = deal(1000);
else
Opt.SNR=1000;
end
for iopt=1:length(Opt) % Test all simulation options
disp(['Testing ' class(Model) ' simulation option:'])
disp(Opt(iopt))
FitResults = Model.Sim_Single_Voxel_Curve(st,Opt(iopt));
% Compare inputs and outputs
fnm=fieldnames(FitResults);
FitResults = rmfield(FitResults,fnm(~ismember(fnm,Model.xnames))); fnm=fieldnames(FitResults);
[~,FitResults,GroundTruth]=comp_struct(FitResults,mat2struct(st,Model.xnames),[],[],.30);
assertTrue(isempty(FitResults) & isempty(GroundTruth),evalc('FitResults, GroundTruth'))
end
disp ..ok

function TestTeardown
setenv('ISDISPLAY','') % go faster! Fit only 2 voxels in FitData.m
setenv('ISCITEST','')


% Copyright 2011 Zdenek Kalal
%
% This file is part of TLD.
%
% TLD 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.
%
% TLD 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 TLD.  If not, see <http://www.gnu.org/licenses/>.

function bb = bb_click_move(img,bb)
% Change

[c,r,p] = impixel(bb_burn(img,bb));

bbW = bb_width(bb);
bbH = bb_height(bb);

bb = [c(1) - bbW/2; r(1) - bbH/2; c(1) + bbW/2; r(1) + bbH/2];


function bool = istequal(t1,t2)

%ISTEQUAL: Compare 2 Matlab time values for equality
%
%USAGE: bool = istequal(t1,t2)
%
%INPUTS: t1,t2 - Matlab formatted date numbers
%
%OUTPUTS: bool - 1 or 0
%
% See also ADD_SST, CHK_T, COMPARE_SST, DELETE_SST, EXTRACT_SST, IS_SST,
%          ISTEQUAL, MERGE_SST, SEARCH_SST, SORT_SST, NAN2SST, SSD2SST,
%          SST2NAN, SST2SSD, SST2VAL, SST2WFA, WFA2SST
%
% Author: Dane Ketner, Alaska Volcano Observatory
% $Date$
% $Revision$

t1 = round(t1*24*60*60*1000); % Units: seconds/1000
t2 = round(t2*24*60*60*1000); % Units: seconds/1000
bool = isequal(t1,t2);


initialImage = im2single( imread('peppers.png') );

width = size(initialImage, 2);
height = size(initialImage, 1);

cropPositions = [ 1, 1, height, width; ... % full image
                  1, 1, height / 2, width / 3; ... % sub patch
                  -height / 2, -width / 2, height / 2, width / 3 ]; ... % sub patch not inside the image
crops = cropRectanglesMex( initialImage, cropPositions, [height, width] );

figure(1), imshow( initialImage );
figure(2), imshow( crops(:,:,:,1) );
figure(3), imshow( crops(:,:,:,2) );
figure(4), imshow( crops(:,:,:,3) );


function MapFig = drawLmk(MapFig,Lmk,MapOpt)

% DRAWLMK  Draw 3D landmark.
%   DRAWLMK(MapFig,Lmk) draws 3D landmark Lmk into the map figure by
%   updating the handles in MapFig structure. It accepts different types of
%   landmark by checking the field Lmk.type. Supported landmark types
%   (June 2009) are:
%       'idpPnt' - inverse depth points
%       'eucPnt' - Euclidean points
%       'hmgPnt' - homogeneous points.
%
%   DRAWLMK(...) draws mean and covariances of landmarks:
%     - For punctual landmarks, the mean is a dot and the covariance is the
%       3/sigma ellipsoid.
%     - For line landmarks, the mean is a segment between the two
%       landmark's endpoints, and the covariance is a 3-sigma ellipsoind at
%       each one of these endpoints.
%
%   See also DRAWIDPPNT, DRAWEUCPNT, DRAWHMGPNT.

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

switch (Lmk.type)

    % landmark types
    % --------------
    case {'idpPnt'}
        colors = MapOpt.colors.othPnt;
        drawIdpPnt(MapFig, Lmk, colors, MapOpt);

    case {'eucPnt'}
        colors = MapOpt.colors.defPnt;
        drawEucPnt(MapFig, Lmk, colors, MapOpt);

    case {'hmgPnt'}
        colors = MapOpt.colors.othPnt;
        drawHmgPnt(MapFig, Lmk, colors, MapOpt);

    case {'ahmPnt'}
        colors = MapOpt.colors.othPnt;
        drawAhmPnt(MapFig, Lmk, colors, MapOpt);

    case {'plkLin'}
        colors = MapOpt.colors.othLin;
        drawPlkLin(MapFig, Lmk, colors, MapOpt);

    case {'aplLin'}
        colors = MapOpt.colors.othLin;
        drawAplLin(MapFig, Lmk, colors, MapOpt);

    case 'idpLin'
        colors = MapOpt.colors.othLin;
        drawIdpLin(MapFig, Lmk, colors, MapOpt);

    case {'hmgLin'}
        colors = MapOpt.colors.othLin;
        drawHmgLin(MapFig, Lmk, colors, MapOpt);

    case {'ahmLin'}
        colors = MapOpt.colors.othLin;
        drawAhmLin(MapFig, Lmk, colors, MapOpt);

    otherwise
        error('??? Unknown landmark type ''%s''.',Lmk.type);

end

% ========== 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