function varargout = montage2( IS, prm )
% Used to display collections of images and videos.
%
% Improved version of montage, with more control over display.
% NOTE: Can convert between MxNxT and MxNx3xT image stack via:
%   I = repmat( I, [1,1,1,3] ); I = permute(I, [1,2,4,3] );
%
% USAGE
%  varargout = montage2( IS, [prm] )
%
% INPUTS
%  IS           - MxNxTxR or MxNxCxTxR, where C==1 or C==3, and R may be 1
%                 or cell vector of MxNxT or MxNxCxT matrices
%  prm
%   .showLines  - [1] whether to show lines separating the various frames
%   .extraInfo  - [0] if 1 then a colorbar is shown as well as impixelinfo
%   .cLim       - [] cLim = [clow chigh] optional scaling of data
%   .mm         - [] #images/col per montage
%   .nn         - [] #images/row per montage
%   .labels     - [] cell array of labels (strings) (T if R==1 else R)
%   .perRow     - [0] only if R>1 and not cell, alternative displays method
%   .hasChn     - [0] if true assumes IS is MxNxCxTxR else MxNxTxR
%   .padAmt     - [0] only if perRow, amount to pad when in row mode
%   .padEl      - [] pad element, defaults to min value in IS
%
% OUTPUTS
%  h           - image handle
%  m           - #images/col
%  nn          - #images/row
%
% EXAMPLE - [3D] show a montage of images
%  load( 'images.mat' ); clf; montage2( images );
%
% EXAMPLE - [3D] show a montage of images with labels
%  load( 'images.mat' );
%  for i=1:50; labels{i}=['I-' int2str2(i,2)]; end
%  prm = struct('extraInfo',1,'perRow',0,'labels',{labels});
%  clf; montage2( images(:,:,1:50), prm );
%
% EXAMPLE - [3D] show a montage of images with color boundaries
%  load( 'images.mat' );
%  I3 = repmat(permute(images,[1 2 4 3]),[1,1,3,1]); % add color chnls
%  prm = struct('padAmt',4,'padEl',[50 180 50],'hasChn',1,'showLines',0);
%  clf; montage2( I3(:,:,:,1:48), prm )
%
% EXAMPLE - [4D] show a montage of several groups of images
%  for i=1:25; labels{i}=['V-' int2str2(i,2)]; end
%  prm = struct('labels',{labels});
%  load( 'images.mat' ); clf; montage2( videos(:,:,:,1:25), prm );
%
% EXAMPLE - [4D] show using 'row' format
%  load( 'images.mat' );
%  prm = struct('perRow',1, 'padAmt',6, 'padEl',255 );
%  figure(1); clf; montage2( videos(:,:,:,1:10), prm );
%
% See also MONTAGE, PLAYMOVIE, FILMSTRIP
%
% Piotr's Computer Vision Matlab Toolbox      Version 2.0
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]

if( nargin<2 ); prm=struct(); end
varargout = cell(1,nargout);

%%% get parameters (set defaults)
dfs = {'showLines',1, 'extraInfo',0, 'cLim',[], 'mm',[], 'nn',[],...
  'labels',[], 'perRow',false, 'padAmt',0, 'padEl',[], 'hasChn',false };
prm = getPrmDflt( prm, dfs );
extraInfo=prm.extraInfo; labels=prm.labels;  perRow=prm.perRow;
hasChn=prm.hasChn;

%%% If IS is not a cell convert to MxNxCxTxR array
if( iscell(IS) && numel(IS)==1 ); IS=IS{1}; end;
if( ~iscell(IS) && ~ismatrix(IS) )
  siz=size(IS);
  if( ~hasChn );
    IS=reshape(IS,[siz(1:2),1,siz(3:end)]);
    prm.hasChn = true;
  end;
  if(ndims(IS)>5); error('montage2: input too large'); end;
end

if( ~iscell(IS) && size(IS,5)==1 ) %%% special case call subMontage once
  [varargout{:}] = subMontage(IS,prm);
  title(inputname(1));

elseif( perRow ) %%% display each montage in row format
  if(iscell(IS)); error('montage2: IS cannot be a cell if perRow'); end;
  siz = size(IS);
  IS=reshape(permute(IS,[1 2 4 3 5]),siz(1),[],siz(3),siz(5));
  if( nargout ); varargout{1}=IS; end
  prm.perRow = false;  prm.hasChn=true;
  [varargout{2:end}] = subMontage( IS, prm );
  title(inputname(1));

else %%% display each montage using subMontage

  % convert to cell array
  if( iscell(IS) )
    nMontages = numel(IS);
  else
    nMontages = size(IS,5);
    IS = squeeze(mat2cell2( IS, [1 1 1 1 nMontages] ));
  end

  % draw each montage
  clf;
  nn = ceil( sqrt(nMontages) ); mm = ceil(nMontages/nn);
  for i=1:nMontages
    subplot(mm,nn,i);
    prmSub=prm;  prmSub.extraInfo=0;  prmSub.labels=[];
    if( ~isempty(IS{i}) )
      subMontage( IS{i}, prmSub );
    else
      set(gca,'XTick',[]); set(gca,'YTick',[]);
    end
    if(~isempty(labels)); title(labels{i}); end
  end
  if( extraInfo ); impixelinfo; end;
end

function varargout = subMontage( IS, prm )
% this function is a generalized version of Matlab's montage.m

% get parameters (set defaults)
dfs = {'showLines',1, 'extraInfo',0, 'cLim',[], 'mm',[], 'nn',[], ...
  'labels',[], 'perRow',false, 'hasChn',false, 'padAmt',0, 'padEl',[] };
prm = getPrmDflt( prm, dfs );
showLines=prm.showLines;   extraInfo=prm.extraInfo;  cLim=prm.cLim;
mm=prm.mm; nn=prm.nn;  labels=prm.labels;  hasChn=prm.hasChn;
padAmt=prm.padAmt;  padEl=prm.padEl;
if( prm.perRow ); mm=1; end;

% get/test image format info and parameters
if( hasChn )
  if( ndims(IS)>4 || ~any(size(IS,3)==[1 3]) )
    error('montage2: unsupported dimension of IS'); end
else
  if( ndims(IS)>3 );
    error('montage2: unsupported dimension of IS'); end
  IS = permute(IS, [1 2 4 3] );
end
siz = size(IS);  nCh=size(IS,3);  nIm = size(IS,4);  sizPad=siz+padAmt;
if( ~isempty(labels) && nIm~=length(labels) )
  error('montage2: incorrect number of labels');
end

% set up the padEl correctly (must have same type / nCh as IS)
if(isempty(padEl))
  if(isempty(cLim)); padEl=min(IS(:)); else padEl=cLim(1); end; end
if(length(padEl)==1); padEl=repmat(padEl,[1 nCh]); end;
if(length(padEl)~=nCh); error( 'invalid padEl' ); end;
padEl = feval( class(IS), padEl );
padEl = reshape( padEl, 1, 1, [] );
padAmt = floor(padAmt/2 + .5)*2;

% get layout of images (mm=#images/row, nn=#images/col)
if( isempty(mm) || isempty(nn))
  if( isempty(mm) && isempty(nn))
    nn = min( ceil(sqrt(sizPad(1)*nIm/sizPad(2))), nIm );
    mm = ceil( nIm/nn );
  elseif( isempty(mm) )
    nn = min( nn, nIm );
    mm = ceil(nIm/nn);
  else
    mm = min( mm, nIm );
    nn = ceil(nIm/mm);
  end
  % often can shrink dimension further
  while((mm-1)*nn>=nIm); mm=mm-1; end;
  while((nn-1)*mm>=nIm); nn=nn-1; end;
end

% Calculate I (M*mm x N*nn size image)
I = repmat(padEl, [mm*sizPad(1), nn*sizPad(2), 1]);
rows = 1:siz(1); cols = 1:siz(2);
for k=1:nIm
  rowsK = rows + floor((k-1)/nn)*sizPad(1)+padAmt/2;
  colsK = cols + mod(k-1,nn)*sizPad(2)+padAmt/2;
  I(rowsK,colsK,:) = IS(:,:,:,k);
end

% display I
if( ~isempty(cLim)); h=imagesc(I,cLim);  else  h=imagesc(I);  end
colormap(gray);  axis('image');
if( extraInfo )
  colorbar; impixelinfo;
else
  set(gca,'Visible','off')
end

% draw lines separating frames
if( showLines )
  montageWd = nn * sizPad(2) + .5;
  montageHt = mm * sizPad(1) + .5;
  for i=1:mm-1
    ht = i*sizPad(1) +.5; line([.5,montageWd],[ht,ht]);
  end
  for i=1:nn-1
    wd = i*sizPad(2) +.5; line([wd,wd],[.5,montageHt]);
  end
end

% plot text labels
textalign = { 'VerticalAlignment','bottom','HorizontalAlignment','left'};
if( ~isempty(labels) )
  count=1;
  for i=1:mm;
    for j=1:nn
      if( count<=nIm )
        rStr = i*sizPad(1)-padAmt/2;
        cStr =(j-1+.1)*sizPad(2)+padAmt/2;
        text(cStr,rStr,labels{count},'color','r',textalign{:});
        count = count+1;
      end
    end
  end
end

% cross out unused frames
[nns,mms] = ind2sub( [nn,mm], nIm+1 );
for i=mms-1:mm-1
  for j=nns-1:nn-1,
    rStr = i*sizPad(1)+.5+padAmt/2; rs = [rStr,rStr+siz(1)];
    cStr = j*sizPad(2)+.5+padAmt/2; cs = [cStr,cStr+siz(2)];
    line( cs, rs );  line( fliplr(cs), rs );
  end
end

% optional output
if( nargout>0 ); varargout={h,mm,nn}; end


%% <../index.html MATLAB xUnit Test Framework>: How to Run a Specific Test
% To run all the test cases in just one M-file, ignoring other test
% cases that might be in other files in the same directory, give
% the name of the file (without the ".m" extension) as an argument
% to |runtests|.
%
% For example

cd example_subfunction_tests

runtests testFliplr

%%
% To run a single test case, add the name of the test case using a
% colon (":"), like this:

runtests testFliplr:testFliplrVector

%%
% <../index.html Back to MATLAB xUnit Test Framework>

%%
% Copyright 2008-2010 The MathWorks, Inc.


function [ readerobj ] = open_mbw_reader(filename)
%OPEN_MBW_READER Intiates a reader object for a multi-band wrapper file
%
% An intermediate format just for handling data that is contained in
% multiple files (color, polarimetric, etc.)
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

%% Read mbw fields
fid=fopen(filename,'r');
while ~feof(fid)
    [fieldname,value]=strtok(fgetl(fid),'=');
    if ~isempty(value)
        mbw.(fieldname)=value(2:end);
        doubval=str2double(mbw.(fieldname));
        if(~isnan(doubval)) % If value is numeric, store as such
            mbw.(fieldname)=doubval;
        end
    end
end
fclose(fid);
if(strcmp(mbw.TYPE,'RGB'))
    for i=1:3, filenamelist{i}=mbw.(mbw.TYPE(i)); end
    readerobj=open_stacked_set(filenamelist{:});
end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////


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

%%
clear; close all; clc;

%% Syntax
% |[theta,w]=rot2VecAngle(R);|

%% 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 BodyCenteredInertialFrame < AbstractReferenceFrame
    %BodyCenteredInertialFrame Summary of this class goes here
    %   Detailed explanation goes here

    properties
        bodyInfo KSPTOT_BodyInfo
        celBodyData

        bodyRotMatFromGlobalInertialToBodyInertial(3,3) double
    end

    properties(Constant)
        typeEnum = ReferenceFrameEnum.BodyCenteredInertial
    end

    methods
        function obj = BodyCenteredInertialFrame(bodyInfo, celBodyData)
            obj.bodyInfo = bodyInfo;
            obj.celBodyData = celBodyData;
            obj.bodyRotMatFromGlobalInertialToBodyInertial = obj.bodyInfo.bodyRotMatFromGlobalInertialToBodyInertial;
        end

        function [posOffsetOrigin, velOffsetOrigin, angVelWrtOrigin, rotMatToInertial] = getOffsetsWrtInertialOrigin(obj, time, ~, ~)
            [rVectB, vVectB] = getPositOfBodyWRTSun(time, [obj.bodyInfo], obj(1).celBodyData);

            posOffsetOrigin = rVectB;
            velOffsetOrigin = vVectB;

            [angVelWrtOrigin, rotMatToInertial] = obj.getAngVelWrtOriginAndRotMatToInertial(time, [], []);
        end

        function rotMatToInertial = getRotMatToInertialAtTime(obj, time, ~, ~)
            if(numel(obj) == 1)
                rotMatToInertial = repmat(obj.bodyRotMatFromGlobalInertialToBodyInertial, [1, 1, length(time)]);

            else
                rotMatToInertial = NaN([3, 3, length(time)]);

                [uniObj,~,ic] = unique(obj,'stable');
                for(i=1:length(uniObj)) %#ok<*NO4LP>
                    subObj = uniObj(i);
                    bool = i == ic;
                    subTimes = time(bool);

                    rotMatToInertial(:,:,bool) = repmat(subObj.bodyRotMatFromGlobalInertialToBodyInertial, [1, 1, numel(subTimes)]);
                end
            end
        end

        function [angVelWrtOrigin, rotMatToInertial] = getAngVelWrtOriginAndRotMatToInertial(obj, time, vehElemSet, bodyInfoInertialOrigin)
            angVelWrtOrigin = repmat([0;0;0], [1, length(time)]);
            rotMatToInertial = obj.getRotMatToInertialAtTime(time, vehElemSet, bodyInfoInertialOrigin);
        end

        function tf = frameOriginIsACelBody(obj)
            tf = true;
        end

        function bodyInfo = getOriginBody(obj)
            bodyInfo = [obj.bodyInfo];
        end

        function setOriginBody(obj, newBodyInfo)
            obj.bodyInfo = newBodyInfo;
        end

        function nameStr = getNameStr(obj)
            nameStr = sprintf('Inertial Frame (Origin: %s)', obj.bodyInfo.name);
        end

        function newFrame = editFrameDialogUI(obj, ~)
            if(isempty(obj.celBodyData))
                obj.celBodyData = obj.bodyInfo.celBodyData;
            end

            [bodiesStr, sortedBodyInfo] = ma_getSortedBodyNames(obj.celBodyData);
            for(i=1:length(sortedBodyInfo))
                sortedBodyInfoArr(i) = sortedBodyInfo{i}; %#ok<AGROW>
            end

            ind = find(obj.bodyInfo == sortedBodyInfoArr,1,'first');

            out = AppDesignerGUIOutput();
            listdlgARH_App('ListString',bodiesStr, 'SelectionMode','single', 'InitialValue',ind, ...
                           'Name','Select Frame Central Body', ...
                           'PromptString', {'Select the central body of the reference frame:'}, ...
                           'ListSize', [250 300], ...
                           'out',out);
            selection = out.output{1};
            ok = out.output{2};

            if(ok == 1)
                newBodyInfo = sortedBodyInfoArr(selection);
                newFrame = BodyCenteredInertialFrame(newBodyInfo, obj.celBodyData);
            else
                newFrame = obj;
            end
        end
    end

    methods
        function bool = eq(A,B)
            try
                if(numel(A) == 1 && numel(B) == 1 && ...
                   A.typeEnum == ReferenceFrameEnum.BodyCenteredInertial && ...
                   B.typeEnum == ReferenceFrameEnum.BodyCenteredInertial)
                    bool = A.bodyInfo == B.bodyInfo;
                else
                    bool = eq@handle(A,B);
                end
            catch ME %#ok<NASGU>
                bool = eq@handle(A,B);
            end
        end

        function bool = ne(A,B)
            bool = not(eq(A,B));
        end
    end

    methods(Static)
        function obj = loadobj(obj)
            obj.bodyRotMatFromGlobalInertialToBodyInertial = obj.bodyInfo.bodyRotMatFromGlobalInertialToBodyInertial;
        end
    end
end


function clean_dir(dir_arg)
% CLEAN_DIR Clean an entire directory of models
%
%
% Inputs:
%   dir_arg  argument for `dir` like '*.OBJ'
%

%addpath ../
files = dir(dir_arg);
for f = 1:numel(files);
  file = files(f).name;
  [path,name,ext] = fileparts(file);
  fprintf('%s...',file);
  [V,F] = load_mesh(file,'Quiet',true);
  mesh_fix_success = true;
  try
    [CV,CF] = meshfix(V,F);
  catch
    fprintf('meshfix crashed...');
    mesh_fix_success = false;
  end
  if size(CF,1) < 0.5*size(F,1)
    fprintf('meshfix removed more than half...');
    tsurf(CF,CV);
    axis equal;
    title(file,'FontSize',15);
    drawnow;
    mesh_fix_success = false;
  end
  if mesh_fix_success
    output_name = fullfile(path,[name '_fixed.obj']);
  else
    try
      [CV,CF] = winding_number_clean(V,F,'SurfaceOnly',true);
      output_name = fullfile(path,[name '_solid.obj']);
    catch(e)
      fprintf('failure.\n');
      continue;
    end
  end
  try
    [CCV,CCT,CCF] = tetgen(CV,CF);
    fprintf('success!\n');
  catch
    fprintf('tetgen failed on CV,CF...');
    fprintf('semi-success?\n');
  end
  tsurf(CF,CV);
  axis equal;
  title(file,'FontSize',15);
  drawnow;
  writeOBJ(output_name,CV,CF);
end

end


%SerialLink.animate   Update a robot animation
%
% R.animate(q) updates an existing animation for the robot R.  This will have
% been created using R.plot().
%
% Updates graphical instances of this robot in all figures.
%
% Notes::
% - Not a general purpose method, used for Simulink robot animation.
%
% See also SerialLink.plot.

function animate(robot, q, handles)

    if nargin < 3
        handles = findobj('Tag', robot.name);
    end

    for handle=handles'     % for each graphical robot instance
        h = get(handle, 'UserData');
        animate2( h, q);
    end

function animate2(h, q)

    robot = h.robot;
    n = robot.n;
    L = robot.links;

    mag = h.mag;

    % compute the link transforms, and record the origin of each frame
    % for the animation.

    % points on the multiline, skeleton of the arm
    x = zeros(1,n);
    y = zeros(1,n);
    z = zeros(1,n);

    % points on the multiline, skeleton of the shadow
    xs = zeros(1,n);
    ys = zeros(1,n);
    zs = zeros(1,n);

    % add first point to the link/shadow line, the base

    t = robot.base;

    x(1) = t(1,4);
    y(1) = t(2,4);
    z(1) = t(3,4);
    xs(1) = t(1,4);
    ys(1) = t(2,4);
    zs(1) = h.zmin;

    Tn = t;  % robot base

    if robot.mdh == 0
        % standard DH parameterization

        % Tn(:,:,j) is pose of joint j
        for j=1:n
            Tn(:,:,j) = t;

            t = t * L(j).A(q(j));

            % add point to arm and shadow skeleton
            %   first point is the base
            x(j+1) = t(1,4);
            y(j+1) = t(2,4);
            z(j+1) = t(3,4);
            xs(j+1) = t(1,4);
            ys(j+1) = t(2,4);
            zs(j+1) = h.zmin;
        end
        t = t *robot.tool;
    else
        % modified DH parameterization
        for j=1:n
                        x(j+1) = t(1,4);
            y(j+1) = t(2,4);
            z(j+1) = t(3,4);
            xs(j+1) = t(1,4);
            ys(j+1) = t(2,4);
            zs(j+1) = h.zmin;

            t = t * L(j).A(q(j));
                        Tn(:,:,j) = t;

            % add point to arm and shadow skeleton
            %   first point is the base

        end
        t = t *robot.tool;

    end

    %
    % draw the robot stick figure and the shadow
    %
    set(h.links,'xdata', x, 'ydata', y, 'zdata', z);
    if isfield(h, 'shadow')
        set(h.shadow,'xdata', xs, 'ydata', ys, 'zdata', zs);
    end

    %
    % display the joints as cylinders with rotation axes
    %
    if isfield(h, 'joint')
        xyz_line = [0 0; 0 0; -2*mag 2*mag; 1 1];

        for j=1:n
            % get coordinate data from the cylinder
            xyz = get(h.joint(j), 'UserData');

            % transform to current joint frame
            xyz = Tn(:,:,j) * xyz;

            % convert to 1-vector
            ncols = numcols(xyz)/2;
            xc = reshape(xyz(1,:), 2, ncols);
            yc = reshape(xyz(2,:), 2, ncols);
            zc = reshape(xyz(3,:), 2, ncols);

            % and update the coordinates of the graphical model
            set(h.joint(j), 'Xdata', xc, 'Ydata', yc, ...
                'Zdata', zc);

            if isfield(h, 'jointaxis')
                % optionally draw the joint axis

                % transform line endpoints to current joint frame
                xyzl = Tn(:,:,j) * xyz_line;

                % and update the graphical line
                set(h.jointaxis(j), 'Xdata', xyzl(1,:), ...
                    'Ydata', xyzl(2,:), ...
                    'Zdata', xyzl(3,:));
                set(h.jointlabel(j), 'Position', xyzl(1:3,1));
            end
        end
    end

    %
    % display the wrist axes and labels
    %
    if isfield(h, 'x')
        %
        % compute the wrist axes, based on final link transformation
        % plus the tool transformation.
        %
        xv = t*[mag;0;0;1];
        yv = t*[0;mag;0;1];
        zv = t*[0;0;mag;1];

        %
        % update the line segments, wrist axis and links
        %
        set(h.x,'xdata',[t(1,4) xv(1)], 'ydata', [t(2,4) xv(2)], ...
            'zdata', [t(3,4) xv(3)]);
        set(h.y,'xdata',[t(1,4) yv(1)], 'ydata', [t(2,4) yv(2)], ...
             'zdata', [t(3,4) yv(3)]);
        set(h.z,'xdata',[t(1,4) zv(1)], 'ydata', [t(2,4) zv(2)], ...
             'zdata', [t(3,4) zv(3)]);
        set(h.xt, 'Position', xv(1:3));
        set(h.yt, 'Position', yv(1:3));
        set(h.zt, 'Position', zv(1:3));
    end


function [ ~ ] = intergrate(fname,fname_out,model,FBAsolution,listRxn)
%
% USAGE:
%
%    intergrate(fname, fname_out, model, FBAsolution, listRxn)
%
% INPUTS:
%    fname:               The name fo the file
%    fname_out:           The name of the output XML file name.
%    model:               A COBRA model structure
%    FBAsolution:         FBA results of a COBRA simulation by the
%                         `optimizeCbModel` function
%    listRxn:             A list of reaction IDs, after which the flux values are modified
%                         or added. P.s., the reaction IDs must be present in both the
%                         parsed CD model and the COBRA model structures. the reactions
%                         can be examined by `cmpR` function.
%
% OUTPUT:
%    fname_out:           A new XML file with the width of reaction links
%                         changed according to flux values calculated by COBRA
%
% EXAMPLE:
%
%    intergrate('anno_test.xml', 'anno_test_2_ecoli.xml', model_ecoli,solution, model_ecoli.rxns(:))
%
% .. Author: - Longfei Mao April, 2015

FBA_result=FBAsolution;
[parsed] = parseCD(fname);   % Parse a CellDesigner XML file into a CD Matlab structure
[ref,normalizedFlux] = addFlux(model,FBA_result,parsed,listRxn) % Overaly the flux distribution with the CD Matlab structure
[annotedText] = writeXML(fname,parsed,fname_out); % Write the CD Matlab strcuture to a new CD XML file.


function [gKern, gVarmeans, gVarcovars, gInd] = whiteVardistPsi1Gradient(whitekern, vardist, Z, covGrad, learnInducing)

% WHITEVARDISTPSI1GRADIENT Compute gradient of white variational Psi1.
% FORMAT
% DESC description here.
% RETURN gKern :
% RETURN gVarmeans :
% RETURN gVarcovars :
% RETURN gInd :
% ARG whitekern : the kernel structure associated with the white kernel.
% ARG vardist :
% ARG Z :
% ARG covGrad :
%
% SEEALSO :
%
% COPYRIGHT : Michalis K. Titsias, 2009
%

% VARGPLVM

gKern = 0;
gVarmeans = zeros(1,prod(size(vardist.means)));
gInd = zeros(1,prod(size(Z)));
gVarcovars = zeros(1,prod(size(vardist.covars)));


function pstruct = tapas_unitsq_sgm_mu3_namep(pvec)
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2018 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

pstruct = struct;

return;


% pop_export() - export EEG dataset
%
% Usage:
%   >> com = pop_export(EEG);   % a window pops up
%   >> com = pop_export(EEG, filename, 'key', 'val', ... );
%
% Inputs:
%   EEG            - eeglab dataset
%   filename       - file name
%
% Optional inputs:
%   'ica'          - ['on'|'off'] export ICA activities (or ERP). Default 'off'.
%   'time'         - ['on'|'off'] include time values. Default 'on'.
%   'timeunit'     - [float] time unit rel. to seconds. Default: 1E-3 = msec.
%   'elec'         - ['on'|'off'] include electrodes names or component numbers.
%                    Default 'on'.
%   'transpose'    - ['on'|'off'] 'off'-> electrode data = rows; 'on' -> electrode
%                    data = columns. Default 'off'.
%   'erp'          - ['on'|'off'] export ERP instead of raw data. Default 'off'.
%   'expr'         - [string] evaluate epxression on data. The expression must
%                    contain a variable 'x' representing the 2-D or 3-D data.
%   'precision'    - [float] number of significant digits in output. Default 4.
%
% Outputs:
%   com            - The expresion that execute this function. i.e. 'pop_export(MyEEG, 'ExpEEG.mat')'
%
% Note: tabulation are used as a delimiter.
%
% Author: Arnaud Delorme, CNL / Salk Institute, May 13, 2003

% Copyright (C) May 13, 2003, Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function com = pop_export(EEG, filename, varargin);

com = '';
if nargin < 1
    help pop_export;
    return;
end;

if nargin < 2
    commandload = [ '[filename, filepath] = uiputfile(''*'', ''Select a text file'');' ...
                    'if filename ~=0,' ...
                    '   set(findobj(''parent'', gcbf, ''tag'', ''tagedit''), ''string'', [ filepath filename ]);' ...
                    'end;' ...
                    'clear filename filepath tagtest;' ];

   uilist = { { 'style' 'text' 'string' 'Output file name' }, ...
              { 'style' 'edit' 'string' '' 'tag' 'tagedit' }, ...
              { 'style' 'pushbutton' 'string' 'Browse' 'callback' commandload },...
              { 'style' 'text' 'string' 'Export ICA activities instead of EEG data:' }, ...
              { 'style' 'checkbox' 'string' '' }, { },{ },  ...
              { 'style' 'text' 'string' 'Export ERP average instead of trials:' }, ...
              { 'style' 'checkbox' 'string' '' }, { }, { }, ...
              { 'style' 'text' 'string' 'Transpose matrix (elec -> rows):' }, ...
              { 'style' 'checkbox' 'string' '' }, { }, { }, ...
              { 'style' 'text' 'string' 'Export channel labels/component numbers:' }, ...
              { 'style' 'checkbox' 'string' '' 'value' 1 }, { }, { }, ...
              { 'style' 'text' 'string' 'Export time values:' }, ...
              { 'style' 'checkbox' 'string' '' 'value' 1 }, ...
              { 'style' 'text' 'string' 'Unit (re. sec)' }, { 'style' 'edit' 'string' '1E-3' }, ...
              { 'style' 'text' 'string' 'Number of significant digits to output:' }, ...
              { 'style' 'edit' 'string' '4' }, { }, { }, ...
              { 'style' 'text' 'string' 'Apply an expression to the output (see ''expr'' help):'} , ...
              { 'style' 'edit' 'string' '' } { } { } };
   bcheck = [1.7 0.25 0.7 0.6];
   uigeom = { [1 2 0.5] bcheck bcheck bcheck bcheck bcheck [3 0.7 0.8 0.6] [3 2 0.05 0.05] };
   result = inputgui( uigeom, uilist, 'pophelp(''pop_export'');', 'Export data - pop_export()' );
   if length( result ) == 0 return; end;

   % decode options
   % --------------
   if isempty(result{1}), error('File name required'); end;
   filename = result{1};
   options = {};
   if result{2},  options = { options{:} 'ica' 'on' }; end;
   if result{3},  options = { options{:} 'erp' 'on' }; end;
   if result{4},  options = { options{:} 'transpose' 'on' }; end;
   if ~result{5}, options = { options{:} 'elec' 'off' }; end;
   if ~result{6}, options = { options{:} 'time' 'off' }; end;
   if ~strcmpi(result{7}, '1E-3'), options = { options{:} 'timeunit' eval(result{7}) }; end;
   if ~strcmpi(result{8}, '4'),    options = { options{:} 'precision' eval(result{8}) }; end;
   if ~isempty(result{9}), options = { options{:} 'expr' result{9} }; end;
else
    options = varargin;
end;

% test inputs
% -----------
g = finputcheck(options, { ...
    'ica'       'string'    { 'on' 'off' }     'off';
    'time'      'string'    { 'on' 'off' }     'on';
    'timeunit'  'float'     [0 Inf]            1E-3;
    'elec'      'string'    { 'on' 'off' }     'on';
    'transpose' 'string'    { 'on' 'off' }     'off';
    'erp'       'string'    { 'on' 'off' }     'off';
    'precision' 'integer'   [0 Inf]            4;
    'expr'      'string'    []                 '' }, 'pop_export');
if isstr(g), error(g); end;

% select data
% ----------
if strcmpi(g.ica, 'on');
    eeglab_options; % changed from eeglaboptions 3/30/02 -sm
	if option_computeica
		x = EEG.icaact;
	else
        x = EEG.icaweights*EEG.icasphere*reshape(EEG.data(EEG.icachansind,:,:), length(EEG.icachansind), EEG.trials*EEG.pnts);
        x = reshape(x, size(x,1), EEG.pnts, EEG.trials);
    end;
else
    x = EEG.data;
end;

% select erp
% ----------
if strcmpi(g.erp, 'on');
    x = mean(x, 3);
else
    x = reshape(x, size(x,1), size(x,2)*size(x,3));
end;

% write data
% ----------
if ~isempty(g.expr)
    eval([ g.expr ';' ]);
end;

% add time axis
% -------------
if strcmpi(g.time, 'on');
    timeind = repmat( linspace(EEG.xmin, EEG.xmax, EEG.pnts)/g.timeunit, ...
                      [ 1 fastif(strcmpi(g.erp,'on'), 1, EEG.trials) ]);
    xx = zeros(size(x,1)+1, size(x,2));
    xx(1,:)     = timeind;
    xx(2:end,:) = x;
    x = xx; clear xx;
end

% transpose and write to disk
% ---------------------------
fid = fopen(filename, 'w');
if strcmpi(g.transpose, 'on');
    % writing electrodes
    % ------------------
    strprintf = '';
    for index = 1:size(x,1)
        if strcmpi(g.time, 'on'), tmpind = index-1;
        else                      tmpind = index;
        end;
        if strcmpi(g.elec, 'on')
            if tmpind > 0
                if ~isempty(EEG.chanlocs) & ~strcmpi(g.ica, 'on')
                    fprintf(fid, '%s\t', EEG.chanlocs(tmpind).labels);
                else fprintf(fid, '%d\t', tmpind);
                end;
            else
                fprintf(fid, ' \t');
            end;
        end;
        strprintf = [ strprintf '%.' num2str(g.precision) 'f\t' ];
    end;
    strprintf(end) = 'n';
    if strcmpi(g.elec, 'on'), fprintf(fid, '\n'); end;
    fprintf(fid, strprintf, x);
else
    % writing electrodes
    % ------------------
    for index = 1:size(x,1)
        if strcmpi(g.time, 'on'), tmpind = index-1;
        else                      tmpind = index;
        end;
        if strcmpi(g.elec, 'on')
            if tmpind > 0
                if ~isempty(EEG.chanlocs) & ~strcmpi(g.ica, 'on')
                    fprintf(fid,'%s\t', EEG.chanlocs(tmpind).labels);
                else fprintf(fid,'%d\t', tmpind);
                end;
            else
                fprintf(fid, ' \t');
            end;
        end;
        fprintf(fid,[ '%.' num2str(g.precision) 'f\t' ], x(index, :));
        fprintf(fid, '\n');
    end;
end;
fclose(fid);

com = sprintf('pop_export(%s,%s);', inputname(1), vararg2str({ filename, options{:} }));
return;


function H= plot_scalpPatternsPlusChannel(erp, mnt, clab, ival, varargin)
%PLOT_SCALPPATTERNSPLUSCHANNEL - Display Classwise topographies and one channel
%
%Synposis:
% H= plot_scalpPatternsPlusChannel(ERP, MNT, CLAB, IVAL, <OPTS>)
%
%Input:
% ERP:  struct of epoched EEG data
% MNT:  struct defining an electrode montage
% CLAB: label of the channel(s) which are to be displayed in the
%        ERP plot.
% IVAL: time interval for which scalp topographies are to be plotted.
%       May be either one interval for all Classes, or specific
%       intervals for each Class. In the latter case the k-th row of IVAL
%       defines the interval for the k-th Class.
% OPTS: struct or property/value list of optional fields/properties:
%  .LegendPos - specifies the position of the legend in the ERP plot,
%               default 'best' (see man page of legend for choices).
%  .MarkIval  - When true, the time interval is marked in the channel plot.
%
%The opts struct is passed to plot_scalpPattern
%
%Output:
% H: Handle to several graphical objects
%
%See also plot_scalpPatterns, plot_scalpEvolutionPlusChannel, plot_scalp.

% Author(s): Benjamin Blankertz, Jan 2005

props = {'LineWidth',           3,                  'DOUBLE';
         'IvalColor',           0.85*[1 1 1],       'DOUBLE[3]';
         'ColorOrder',          [0 0 0],            'DOUBLE[3]';
         'MarkIval',            0,                  'BOOL';
         'XGrid',               'on',               'CHAR';
         'YGrid',               'on',               'CHAR';
         'XUnit',               '[ms]',             'CHAR';
         'PlotChannel',         1,                  'BOOL';
         'ScalePos',            'vert',             'CHAR';
         'LegendPos',           'best',             'CHAR';
         'NewColormap',         0,                  'BOOL';
         'MarkPatterns',        [],                 'DOUBLE|CHAR';
         'MarkStyle',           {'LineWidth',3},    'CELL';
         'Subplot',             [],                 'DOUBLE'};

props_scalpPattern= plot_scalpPattern;
props_channel= plotutil_channel1D;

if nargin==0,
  H= opt_catProps(props, props_scalpPattern, props_channel); return
end

opt= opt_proplistToStruct(varargin{:});
[opt,isdefault]= opt_setDefaults(opt, props);
opt_checkProplist(opt, props, props_scalpPattern, props_channel);
[opt,isdefault] = opt_overrideIfDefault(opt,isdefault, 'MarkIval',size(ival,1)==1,'PlotChannel',~isempty(clab));

opt_scalpPattern= opt_substruct(opt, props_scalpPattern(:,1));
opt_channel= opt_substruct(opt, props_channel(:,1));

misc_checkType(erp,'!STRUCT(x y className)');
misc_checkType(mnt,'!STRUCT(x)');

if nargin<4 || isempty(ival),
  ival= [NaN NaN]; %erp.t([1 end]);
elseif size(ival,2)==1,
  ival= [ival ival];
elseif size(ival,2)>2,
  error('IVAL must be sized [N 2]');
end

if isfield(erp, 'XUnit'),
  [opt,isdefault]= opt_overrideIfDefault(opt, isdefault, 'XUnit', erp.xUnit);
end

if max(sum(erp.y,2))>1,
  erp= proc_average(erp);
end
nClasses= length(erp.className);

% Diese Abfrage ist nicht korrekt, da alle Felder schon gesetzt sein
% muessen
if ~isfield(opt, 'CLim') && all(erp.x>=0),
  opt.CLim= 'range';
  warning('automatically set opt.CLim= ''range''.');
end

if ischar(opt.MarkPatterns),
  if ~strcmpi(opt.MarkPatterns, 'all'),
    warning('unknown value for opt.MarkPatterns ignored');
  end
  opt.MarkPatterns= 1:nPat;
end

[AxesStyle, lineStyle]= opt_extractPlotStyles(opt);
nIvals= size(ival,1);
if nIvals<nClasses,
  ival= repmat(ival, [nClasses, 1]);
end

if opt.NewColormap,
  acm= visutil_addColormap(opt.Colormap);
end
if isempty(opt.Subplot),
  clf;
end
for cc= 1:nClasses,
  if isempty(opt.Subplot),
    subplotxl(1, nClasses+opt.PlotChannel, cc+opt.PlotChannel, ...
              0.07, [0.07 0.02 0.1]);
  else
    axis_getQuietly(opt.Subplot(cc));
  end
  opt_scalpPattern= setfield(opt_scalpPattern, 'ScalePos','none');
  if opt.NewColormap,
    opt_scalpPattern= rmfield(opt_scalpPattern, 'Colormap');
    opt_scalpPattern= setfield(opt_scalpPattern, 'NewColormap',0);
  end
  opt_scalpPattern.Class= cc;
  clscol= opt.ColorOrder(min(cc,size(opt.ColorOrder,1)),:);
  opt_scalpPattern= opt_setDefaults(opt_scalpPattern, 'Linespec', {'linewidth',2, 'Color',clscol});
  h.H_topo(cc)= plot_scalpPattern(erp, mnt, ival(cc,:), opt_scalpPattern);
  if ismember(cc, opt.MarkPatterns,'legacy'),
    set([h.H_topo(cc).head h.H_topo(cc).nose], opt.MarkStyle{:});
  end
  yLim= get(gca, 'yLim');
  h.text(cc)= text(mean(xlim), yLim(2)+0.06*diff(yLim), erp.className{cc});
  set(h.text(cc), 'Color',clscol);
  if ~any(isnan(ival(cc,:))),
    ival_str= sprintf('%g - %g %s', ival(cc,:), opt.XUnit);
  else
    ival_str= '';
  end
  h.text_ival(cc)= text(mean(xlim), yLim(1)-0.04*diff(yLim), ival_str);
%  axis_aspectRatioToPosition;   %% makes Colorbar appear in correct size
end
set(h.text, 'horizontalAli','center', ...
            'Visible','on', ...
            'FontSize',12, 'fontWeight','bold');
set(h.text_ival, 'verticalAli','top', 'horizontalAli','center', ...
                 'Visible','on');
if ismember(opt.ScalePos, {'horiz','vert'},'legacy'),
  h.cb= plotutil_colorbarAside(opt.ScalePos);
  % hack to fix a matlab bug
  ud= get(h.cb, 'UserData');
  ud.orientation= opt.ScalePos;
  set(h.cb, 'UserData',ud);
  % put YUnit on top of Colorbar
  if isfield(erp, 'yUnit'),
    axes(h.cb);
    yl= get(h.cb, 'YLim');
    h.YUnit= text(mean(xlim), yl(2), erp.yUnit);
    set(h.YUnit, 'horizontalAli','center', 'verticalAli','bottom');
  end
  if nClasses>1,
%    visutil_unifyCLim([h.H_topo.ax], [zeros(1,nClasses-1) h.cb]);
    visutil_unifyCLim([h.H_topo.ax]);
  end
elseif nClasses>1,
  visutil_unifyCLim([h.H_topo.ax], [zeros(1,nClasses)]);
end
if opt.NewColormap,
  visutil_acmAdaptCLim(acm, [h.H_topo.ax]);
end

if opt.PlotChannel,
  if isempty(opt.Subplot),
    h.ax_erp= subplotxl(1, nClasses+1, 1, 0.1, [0.06 0.02 0.1]);
  else
    h.ax_erp= opt.Subplot(nClasses+1);
    axes(h.ax_erp);
  end
  topopos= get(h.H_topo(end).ax, 'position');
  pos= get(h.ax_erp, 'position');
  pos([2 4])= topopos([2 4]);
  set(h.ax_erp, 'position',pos);
  if ~isempty(AxesStyle),
    set(h.ax_erp, AxesStyle{:});
  end
  hold on;   %% otherwise axis properties like ColorOrder are lost
  H.channel= plot_channel(erp, clab, opt_channel, 'legend',0);
  if opt.MarkIval,
    for cc= 1:nIvals,
      grid_markInterval(ival(cc,:), clab, ...
                    opt.IvalColor(min(cc,size(opt.IvalColor,1)),:));
    end
    axis_redrawFrame(h.ax_erp);
  end
  set(get(h.ax_erp, 'title'), 'FontSize',12, 'fontWeight','bold');
  if ~isequal(opt.LegendPos, 'none'),
    h.leg= legend(erp.className, 'Location',opt.LegendPos);
  end
end

if nargout<1,
  clear h
end


function [assocScansV, relStructNumV] = getStructureAssociatedScan(structsV, planC)
%"getStructureAssociatedScan"
%   Returns a vector with the corresponding associated scan for each
%   structure number passed in structsV.
%
%   Structures without an associatedScan field, structures with an empty
%   associatedScan field are assumed to be associated with scan 1.
%
%   Also returns relStructNum, a list of "relative" structure indices for
%   the passed structsV.  This is the number of the structure in the list
%   of all structures with the same associatedScan.
%
%   If planC is not specified, the global planC is used.
%
%JRA 2/15/05
%
%Usage:
%   [assocScansV, relStructNum] = getStructureAssociatedScan(structsV, planC)

% if ~exist('planC')
%     global planC
% end
indexS = planC{end};

%Return if no structures were passed in.
if isempty(structsV)
    assocScansV = [];
    relStructNumV = [];
    return;
end

%If no associated scan field, assume scan 1.
if ~isfield(planC{indexS.structures}, 'associatedScan')
    allAssocScansV = ones(1, length(planC{indexS.structures}));
else
    %If field is blank, assume scan 1, else take field contents.
    for i=1:length(planC{indexS.structures})
        if isempty(planC{indexS.structures}(i).associatedScan)
            allAssocScansV(i) = 1;
        else
            allAssocScansV(i) = planC{indexS.structures}(i).associatedScan;
        end
    end
end

%Return only requested structures' assocScans.
assocScansV = allAssocScansV(structsV);

%Calculate relativeStructNum for all structures.
allScans = unique(allAssocScansV);
for i=1:length(allScans)
    scanNum = allScans(i);
    matchingIndV = find(allAssocScansV == scanNum);
    allRelStructNumV(matchingIndV) = 1:length(matchingIndV);
end

%Only return relStructNum for the requested structs.
relStructNumV = allRelStructNumV(structsV);


function preserve_history ()
% Maintains command history indefinitely in a separate history_saved.m file
% since Matlab is truncating history.m to a fixed size. The code is fast even
% when history_saved.m gets very big.
%
% Also works with the new format introduced in R2014a which is XML. Its
% contents are parsed as plain commands and merged into history_saved.m
%
% Bogdan Roman, 2014, abr28@cam.ac.uk, University of Cambridge

savpath = fullfile(prefdir,'history_saved.m');

% If History.xml exists (R2014a or later) read that, else revert to history.m
hpath = fullfile(prefdir,'History.xml');
if exist(hpath,'file')
    % Read the XML file into a string to look as the older history.m (i.e.
    % remove all XML tags)
    mathist = fileread(hpath);
    mathist = regexprep(mathist, '(<[^>]+>\s*)+', '\n', 'lineanchors');
    % translate html entities and remove leading newline
    mathist = strrep(mathist(3:end), '>', '>');
    mathist = strrep(mathist, '<', '<');
else
    mathist = fileread(fullfile(prefdir,'history.m'));
end

% replace \r and \r\n with \n (safe to copy between OSes)
mathist = regexprep(mathist, '\r(\n)?', '\n');

fprintf('Merging current command history into %s ...\n', savpath);

% if empty saved file, dump it all
if ~exist(savpath,'file')
    fid = fopen(savpath, 'w');
    fwrite(fid, mathist);
    fclose(fid);
    return;
end

% Read saved file fully and use regexp(). Faster than parsing line by line.
savhist = fileread(savpath);
%savhist = regexprep(savhist, '\r(\n)?', '\n');

% Look for last saved date in the preserved file. Must be a valid date and
% not 'Unknown date', which may match in both files and overwrite the entire
% saved history. Note the \d to that effect.
[savstart, savend] = regexp(savhist,'^%-- \d.*?$','lineanchors');
if isempty(savstart)
    % If none found, then append current history entirely
    fid = fopen(savpath,'a');
    fwrite(fid, mathist);
    fclose(fid);
else
    % Extract last save date as string and search for it in current history
    savlastdate = savhist(savstart(end):savend(end)-1);
    matstart = regexp(mathist, ['^' savlastdate], 'lineanchors');
    % If not found, append the entire current history
    if isempty(matstart)
        fid = fopen(savpath,'a');
        fwrite(fid, mathist);
        fclose(fid);
    % Otherwise merge the chunks
    else
        fid = fopen(savpath, 'r+');
        fseek(fid, savstart(end)-1, 'bof');
        fwrite(fid, mathist(matstart(1):end));
        fclose(fid);
    end
end
disp('Done');


function matRad_compileMCsquareSparseReader(dest,sourceFolder)
% Compiles the sparse mcsquare reader as mex interface
% for the current platform
%
% call
%   matRad_compileMCsquareSparseReader()
%   matRad_compileMCsquareSparseReader(dest)
%   matRad_compileMCsquareSparseReader(dest,sourceFolder)
%
% input:
%   dest:           (optional) destination for mex file. Default: location of this
%                   file
%   sourceFolder:   (optional) path to folder. Default: location of this
%                   file
%
% References
%
%   https://aapm.onlinelibrary.wiley.com/doi/abs/10.1118/1.4943377
%   http://www.openmcsquare.org/
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright 2020 the matRad development team.
%
% This file is part of the matRad project. It is subject to the license
% terms in the LICENSE file found in the top-level directory of this
% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
% of the matRad project, including this file, may be copied, modified,
% propagated, or distributed except according to the terms contained in the
% LICENSE file.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

matRad_cfg = MatRad_Config.instance();

if nargin < 1
    dest = fileparts(mfilename('fullpath'));
end

if nargin < 2
    sourceFolder = fileparts(mfilename('fullpath'));
end

if exist ('OCTAVE_VERSION', 'builtin')
    ccName = evalc('mkoctfile -p CXX');
else
    myCCompiler = mex.getCompilerConfigurations('C','Selected');
    ccName = myCCompiler.ShortName;
end

%These settings have only been tested for MSVC and g++. You may need to adapt for other compilers
if ~isempty(strfind(ccName,'MSVC')) %Not use contains(...) because of octave
    flags{1,1} = 'COMPFLAGS';
    flags{1,2} = '/O2';
else
    flags{1,1} = 'CXXFLAGS';
    flags{1,2} = '-std=c++11 -O2 -fPIC';
end

flagstring = '';

%For Octave, the flags will be set in the environment, while they
%will be parsed as string arguments in MATLAB
for flag = 1:size(flags,1)
    if exist ('OCTAVE_VERSION', 'builtin')
        setenv(flags{flag,1},flags{flag,2});
    else
        flagstring = [flagstring flags{flag,1} '="' flags{flag,2} '" '];
    end
end

mexCall = ['mex -largeArrayDims ' flagstring ' ' sourceFolder filesep 'matRad_sparseBeamletsReaderMCsquare.cpp'];

matRad_cfg.dispDebug('Compiler call: %s\n',mexCall);

currDir = pwd;
cd(dest);
eval(mexCall);
cd(currDir);

end


%clear;
clear;
pp = '/home/yutian/re-id/dataset/market1501/bounding_box_test/*.jpg';
%% change ID-level attribute to instance-level attribute
load('market_attribute.mat');
file = dir(pp);
counter_data=1;
counter_last = 1;
class = 0;
c_last = '';
cc = [];
for i=1:length(file)
    c = strsplit(file(i).name,'_');
    if(~isequal(c{1},c_last))
        a = str2num(c{1});
        if a>0
            class = class + 1;
        end
        fprintf('%d::%d\n',class,counter_data-counter_last);
        cc=[cc;counter_data-counter_last];
        c_last = c{1};
        counter_last = counter_data;
    end
    if a>0
        dtupblack(counter_data) = market_attribute.test.upblack(class);
        dtupwhite(counter_data) = market_attribute.test.upwhite(class);
        dtupred(counter_data) = market_attribute.test.upred(class);
        dtuppurple(counter_data) = market_attribute.test.uppurple(class);
        dtupyellow(counter_data) = market_attribute.test.upyellow(class);
        dtupblue(counter_data) = market_attribute.test.upblue(class);
        dtupgreen(counter_data) = market_attribute.test.upgreen(class);
        dtupgray(counter_data) = market_attribute.test.upgray(class);

        dtdownblack(counter_data) = market_attribute.test.downblack(class);
        dtdownwhite(counter_data) = market_attribute.test.downwhite(class);
        dtdownpink(counter_data) = market_attribute.test.downpink(class);
        dtdownpurple(counter_data) = market_attribute.test.downpurple(class);
        dtdownyellow(counter_data) = market_attribute.test.downyellow(class);
        dtdownblue(counter_data) = market_attribute.test.downblue(class);
        dtdowngreen(counter_data) = market_attribute.test.downgreen(class);
        dtdowngray(counter_data) = market_attribute.test.downgray(class);
        dtdownbrown(counter_data) = market_attribute.test.downbrown(class);

        dtup(counter_data) = market_attribute.test.up(class);
        dtgender(counter_data) = market_attribute.test.gender(class);
        dtdown(counter_data) = market_attribute.test.down(class);
        dtclothes(counter_data) = market_attribute.test.clothes(class);
        dthat(counter_data) = market_attribute.test.hat(class);
        dtbackpack(counter_data) = market_attribute.test.backpack(class);
        dthandbag(counter_data) = market_attribute.test.handbag(class);
        dtbag(counter_data) = market_attribute.test.bag(class);
        dtage(counter_data) = market_attribute.test.age(class);
        dthair(counter_data) = market_attribute.test.hair(class);
        counter_data = counter_data + 1;
    end
end
%% evaluate
load('gallery_market.mat')
temp1 = 0;temp2 = 0;temp3 = 0;temp4 = 0;temp5 = 0;temp6 = 0;temp7 = 0;temp8 = 0;
temp9 = 0; temp10 = 0;temp11 = 0; temp12 = 0;
for j = 1:13115
    if (gallery(j,1)==dtgender(j))
        temp1 = temp1+1;
    end
    if (gallery(j,2)==dthair(j))
        temp3 = temp3+1;
    end
    if (gallery(j,3)==dtage(j))
        temp2 = temp2+1;
    end
    if (gallery(j,4)==dtup(j))
        temp4 = temp4+1;
    end
    if (gallery(j,5)==dtdown(j))
        temp5 = temp5+1;
    end
    if (gallery(j,6)==dtclothes(j))
        temp6 = temp6+1;
    end
    if (gallery(j,7)==dthat(j))
        temp10 = temp10+1;
    end
    if (gallery(j,8)==dtbackpack(j))
        temp7 = temp7+1;
    end
    if (gallery(j,9)==dtbag(j))
        temp9 = temp9+1;
    end
    if (gallery(j,10)==dthandbag(j))
        temp8 = temp8+1;
    end
    if(gallery(j,11)==1 && dtupblack(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==2 && dtupwhite(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==3 && dtupred(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==4 && dtuppurple(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==5 && dtupgray(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==6 && dtupblue(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==7 && dtupgreen(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,11)==8 && dtupyellow(j)==2)
        temp11 = temp11+1;
    end
    if(gallery(j,12)==1 && dtdownblack(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==2 && dtdownwhite(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==3 && dtdownpink(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==4 && dtdowngray(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==5 && dtdownblue(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==6 && dtdowngreen(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==7 && dtdownbrown(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==8 && dtdownyellow(j)==2)
        temp12 = temp12+1;
    end
    if(gallery(j,12)==9 && dtdownpurple(j)==2)
        temp12 = temp12+1;
    end
end

precision1 = temp1 /j
precision2 = temp2 /j
precision3 = temp3 /j
precision4 = temp4 /j
precision5 = temp5 /j
precision6 = temp6 /j
precision7 = temp7 /j
precision8 = temp8 /j
precision9 = temp9 /j
precision10 = temp10 /j
precision11 = temp11 /j
precision12 = temp12 /j
average = (precision1+precision2+precision3+precision4+precision5+precision6+precision7+precision8+precision9+precision10+precision11+precision12)/12


function out = InsertDate(in)

%InsertDate - Insert date into string.
%
% Replaces %y, %m, %d and %t with current year, month, day and time.
%
%  USAGE
%
%    out = InsertDate(in)
%
%    in             string to modify

% Copyright (C) 2013 by Michaël Zugaro
%
% 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.

n = clock;
year = int2str(n(1));
month = int2zstr(n(2),2);
day = int2zstr(n(3),2);
time = [int2zstr(n(4)) '' int2zstr(n(5))];

out = in;
out = strrep(out,'%y',year);
out = strrep(out,'%m',month);
out = strrep(out,'%d',day);
out = strrep(out,'%t',time);


%%
clear all; close all; clc

%% set MATLAB path
% set the Explore2p code folder as current directory
if true % set the
    scriptName = mfilename('fullpath');
    [code_dir, filename, fileextension]= fileparts(scriptName);
    addpath(genpath(code_dir));
    cd(code_dir)

else
    % (hard-coded, customize here)
    folder = 'C:\Users\xiuye\Dropbox\!Research\2Pcode\Explore2p'; %#ok<UNRCH>
    addpath(genpath(folder));
    cd(folder)
end

%% Automatically load demo data
% isDemo = true;
%
% %% Start the GUI
% h = Explore2p(isDemo);

% to update the object handle in the workspace, go to the GUI Menu and press
% File\Export to workspace. See demo\demo_workspace_interactive.m

%% For Scripts: see demo\demo_script.m for using Explore2p in custom scripts

%% To load the GUI with non-demo data, simply call -
% Explore2p;


%  Return orientation of the current image:
%	orient is orientation 1x3 matrix, in that:
%	Three elements represent: [x y z]
%	Element value:	1 - Left to Right; 2 - Posterior to Anterior;
%			3 - Inferior to Superior; 4 - Right to Left;
%			5 - Anterior to Posterior; 6 - Superior to Inferior;
%  e.g.:
%	Standard RAS Orientation:	[1 2 3]
%	Standard RHOS Orientation:	[2 4 3]

%  Jimmy Shen (jimmy@rotman-baycrest.on.ca), 26-APR-04
%
function orient = rri_orient_ui(varargin)

   if nargin == 0
      init;
      orient_ui_fig = gcf;
      uiwait;					% wait for user finish

      orient = getappdata(gcf, 'orient');

      if isempty(orient)
         orient = [1 2 3];
      end

      if ishandle(orient_ui_fig)
         close(gcf);
      end

      return;
   end

   action = varargin{1};

   if strcmp(action, 'done')
      click_done;
   elseif strcmp(action, 'cancel')
      uiresume;
   end

   return;						% rri_orient_ui

%----------------------------------------------------------------------
function init

   save_setting_status = 'on';
   rri_orient_pos = [];

   try
      load('pls_profile');
   catch
   end

   try
      load('rri_pos_profile');
   catch
   end

   if ~isempty(rri_orient_pos) & strcmp(save_setting_status,'on')

      pos = rri_orient_pos;

   else

      w = 0.35;
      h = 0.4;
      x = (1-w)/2;
      y = (1-h)/2;

      pos = [x y w h];

   end

   handles.figure = figure('Color',[0.8 0.8 0.8], ...
        'Units','normal', ...
        'Name', 'Convert to standard RAS orientation', ...
        'NumberTitle','off', ...
        'MenuBar','none', ...
        'Position',pos, ...
        'WindowStyle', 'normal', ...
        'ToolBar','none');

   h0 = handles.figure;
   Font.FontUnits  = 'point';
   Font.FontSize   = 12;

   margin = .1;
   line_num = 6;
   line_ht = (1 - margin*2) / line_num;

   x = margin;
   y = 1 - margin - line_ht;
   w = 1 - margin * 2;
   h = line_ht * .7;

   pos = [x y w h];

   handles.Ttit = uicontrol('parent', h0, ...
	'style','text', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'background', [0.8 0.8 0.8], ...
	'string', 'Please input orientation of the current image:');

   y = y - line_ht;
   w = .2;

   pos = [x y w h];

   handles.Tx_orient = uicontrol('parent', h0, ...
	'style','text', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'background', [0.8 0.8 0.8], ...
	'string', 'X   Axes:');

   y = y - line_ht;

   pos = [x y w h];

   handles.Ty_orient = uicontrol('parent', h0, ...
	'style','text', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'background', [0.8 0.8 0.8], ...
	'string', 'Y   Axes:');

   y = y - line_ht;

   pos = [x y w h];

   handles.Tz_orient = uicontrol('parent', h0, ...
	'style','text', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'background', [0.8 0.8 0.8], ...
	'string', 'Z   Axes:');

   choice = {	'From Left to Right', 'From Posterior to Anterior', ...
		'From Inferior to Superior', 'From Right to Left', ...
		'From Anterior to Posterior', 'From Superior to Inferior'	};

   y = 1 - margin - line_ht;
   y = y - line_ht;
   w = 1 - margin - x - w;
   x = 1 - margin - w;

   pos = [x y w h];

   handles.x_orient = uicontrol('parent', h0, ...
	'style','popupmenu', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'string', choice, ...
	'value', 1, ...
	'background', [1 1 1]);

   y = y - line_ht;

   pos = [x y w h];

   handles.y_orient = uicontrol('parent', h0, ...
	'style','popupmenu', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'string', choice, ...
	'value', 2, ...
	'background', [1 1 1]);

   y = y - line_ht;

   pos = [x y w h];

   handles.z_orient = uicontrol('parent', h0, ...
	'style','popupmenu', ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','left',...
	'string', choice, ...
	'value', 3, ...
	'background', [1 1 1]);

   x = margin;
   y = y - line_ht * 1.5;
   w = .3;

   pos = [x y w h];

   handles.done = uicontrol('parent', h0, ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','center',...
        'callback', 'rri_orient_ui(''done'');', ...
	'string', 'Done');

   x = 1 - margin - w;

   pos = [x y w h];

   handles.cancel = uicontrol('parent', h0, ...
	'unit', 'normal', ...
	Font, ...
	'Position',pos, ...
	'HorizontalAlignment','center',...
        'callback', 'rri_orient_ui(''cancel'');', ...
	'string', 'Cancel');

   setappdata(h0, 'handles', handles);
   setappdata(h0, 'orient', [1 2 3]);

   return;						% init

%----------------------------------------------------------------------
function click_done

   handles = getappdata(gcf, 'handles');

   x_orient = get(handles.x_orient, 'value');
   y_orient = get(handles.y_orient, 'value');
   z_orient = get(handles.z_orient, 'value');

   orient = [x_orient y_orient z_orient];
   test_orient = [orient, orient + 3];
   test_orient = mod(test_orient, 3);

   if length(unique(test_orient)) ~= 3
      msgbox('Please don''t choose same or opposite direction','Error','modal');
      return;
   end

   setappdata(gcf, 'orient', [x_orient y_orient z_orient]);
   uiresume;

   return;						% click_done


% APM Report Problem Details
%
% y = apm_details(server,app,x,lam)
%
% This function reports the details of a problem
%   located on the APM server with the following arguments:
%
%   server = address of server
%      app = application name
%        x = values of all variables
%      lam = Lagrange multipliers
%        y = structure with problem information
%
% Reports model details such as values, multipliers, residuals,
%   first derivatives, and second derivatives
%
%      y.nvar  = number of variables
%    y.var.lb  = variable lower bounds
%    y.var.val = variable values
%    y.var.ub  = variable upper bounds
%        y.obj = objective value
%   y.obj_grad = objective gradient
%       y.neqn = number of equations
%     y.eqn.lb = equation lower bounds
%    y.eqn.res = equation residuals
%     y.eqn.ub = equation upper bounds
%        y.jac = jacobian (1st derivatives)
%        y.lam = lagrange multipliers
%    y.hes_obj = second derivative of the objective
% y.hes_eqn{i} = second derivatives of equation {i}
%        y.hes = full Hessian
%
function y = apm_details(server,app,x,lam)

persistent sol_prev sol_count

% initialize sol_count
if (isempty(sol_count)),
    sol_count = 0;
end

% tolerance for checking if the values are the same
%   as the previous call
tol = 1e-10;

% optionally load solution vector of variables
if (nargin>=3),
    % create 'warm' as a column vector
    if (size(x,1)==1),
        warm = x';
    else
        warm = x;
    end

    % see if the values are the same as a previous call
    warm_sum = sum(warm);
    for i = 1:sol_count,
        % check summation of warm first
        if (abs(sol_prev(i).y.sumx-warm_sum) <= tol),
            % check individual elements next
            if (abs(sol_prev(i).y.var.val-warm) <= tol),
                % return previous solution if values haven't changed
                y = sol_prev(i).y;
                return
            end
        end
    end

    % load warm.t0 to the server
    fid = fopen('warm.t0','w');
    fprintf(fid,'%20.12e\n',warm);
    fclose(fid);

    t0_load(server,app,'warm.t0');
    delete('warm.t0');
end

% optionally load lagrange multipliers to server
if (nargin>=4),
    % create 'lam' as a column vector
    if (size(lam,1)==1),
        lam = lam';
    end

    fid = fopen('lam.t0','w');
    fprintf(fid,'%20.12e\n',lam);
    fclose(fid);

    t0_load(server,app,'lam.t0');
    delete('lam.t0');
end

% compute details on server
output = apm(server,app,'solve');

% retrieve variables and bounds
apm_get(server,app,'apm_var.txt');
load apm_var.txt
delete('apm_var.txt');
y.nvar = size(apm_var,1); % get number of variables
y.var.lb = apm_var(:,1);
y.var.val = apm_var(:,2);
y.var.ub = apm_var(:,3);

% retrieve objective function value
apm_get(server,app,'apm_obj.txt');
load apm_obj.txt
delete('apm_obj.txt');
y.obj = apm_obj;

% retrieve objective gradient
apm_get(server,app,'apm_obj_grad.txt');
load apm_obj_grad.txt
delete('apm_obj_grad.txt');
y.obj_grad = apm_obj_grad;

% retrieve equation residuals and bounds
apm_get(server,app,'apm_eqn.txt');
load apm_eqn.txt
delete('apm_eqn.txt');
y.neqn = size(apm_eqn,1); % get number of equations
y.eqn.lb = apm_eqn(:,1);
y.eqn.res = apm_eqn(:,2);
y.eqn.ub = apm_eqn(:,3);

% retrieve jacobian
apm_get(server,app,'apm_jac.txt');
load apm_jac.txt
delete('apm_jac.txt');
jac = apm_jac;
y.jac = sparse(jac(:,1),jac(:,2),jac(:,3),y.neqn,y.nvar);

% retrieve lagrange multipliers
apm_get(server,app,'apm_lam.txt');
load apm_lam.txt
delete('apm_lam.txt');
y.lam = apm_lam;

% retrieve hessian of the objective only
apm_get(server,app,'apm_hes_obj.txt');
load apm_hes_obj.txt
delete('apm_hes_obj.txt');
hs = apm_hes_obj;
y.hes_obj = sparse(hs(:,1),hs(:,2),hs(:,3),y.nvar,y.nvar);

% retrieve hessian of the equations only
apm_get(server,app,'apm_hes_eqn.txt');
load apm_hes_eqn.txt
delete('apm_hes_eqn.txt');
hs = apm_hes_eqn;
nhs = size(apm_hes_eqn,1);
i1(1:y.neqn)=0;
i2(1:y.neqn)=0;
% equations listed in sequential order
for i = 1:nhs,
    if(i1(hs(i,1))==0),
        i1(hs(i,1)) = i;
    end
    i2(hs(i,1)) = i;
end
for i = 1:y.neqn,
    if (i1(i)==0),
        y.hes_eqn{i} = sparse(y.nvar,y.nvar);
    else
        y.hes_eqn{i} = sparse(hs(i1(i):i2(i),2),hs(i1(i):i2(i),3),hs(i1(i):i2(i),4),y.nvar,y.nvar);
    end
end

% construct hessian from obj, lam, and eqn portions
y.hes = y.hes_obj;
for i = 1:y.neqn,
    y.hes = y.hes + y.lam(i) * y.hes_eqn{i};
end

% store values
sol_count = sol_count + 1;
sol_prev(sol_count).y = y;
sol_prev(sol_count).y.sumx = sum(y.var.val);


function fh = plot4D(this, varargin)
%plots an MR image per slice
%
%   Y  = MrImage
%   fh = Y.plot4D('ParameterName', ParameterValue)
%
% IN
%   varargin    'ParameterName', 'ParameterValue'-pairs for the following
%               properties:
%               'plotType'          Type of plot that is created
%                                       'montage'   images are plotted as
%                                                   montages of slices or
%                                                   volumes
%                                       'labeledMontage'
%                                                   as montage, but with
%                                                   slice/volume labels
%                                                   (default)
%                                       'overlay'   overlays of images are
%                                                   plotted with different
%                                                   colormaps (e.g. for
%                                                   activation maps, mask
%                                                   visualization)
%                                       'spm'       uses display functions
%                                                   from SPM (spm_display/
%                                                   spm_check_registration)
%                                                   to visualize 3D volumes
%                                                   with header information
%                                                   applied ("world space")
%                                                   Note: if multiple
%                                                   selected volumes are
%                                                   specified,
%                                                   spm_check_registration
%                                                   is used
%                                       'spmInteractive' /'spmi'
%                                                   same as SPM, but keeps
%                                                   temporary nifti files to
%                                                   allow clicking into spm
%                                                   figure
%                                       '3D'/'3d'/'ortho'
%                                                   See also tapas_uniqc_view3d plot3
%                                                   Plots 3 orthogonal
%                                                   sections
%                                                   (with CrossHair) of
%                                                   3D image interactively
%
%               'displayRange'      [1,2] vector for pixel value = black and
%                                                    pixel value = white
%               'signalPart'        for complex data, defines which signal
%                                   part shall be extracted for plotting
%                                       'all'       - take signal as is
%                                                     (default for
%                                                     real-valued data)
%                                       'abs'       - absolute value
%                                                     (default for complex
%                                                     data)
%                                       'phase'     - phase of signal
%                                       'real'      - real part of signal
%                                       'imag'      - imaginary part of
%                                                     signal
%               'plotMode'          transformation of data before plotting
%                                   'linear' (default), 'log'
%               'selectedVolumes'   [1,nVols] vector of selected volumes to
%                                             be displayed
%               'selectedSlices'    [1,nSlices] vector of selected slices to
%                                               be displayed
%                                   choose Inf to display all volumes
%               'sliceDimension'    (default: 3) determines which dimension
%                                   shall be plotted as a slice
%               'rotate90'          default: 0; 0,1,2,3; rotates image
%                                   by multiple of 90 degrees AFTER
%                                   flipping slice dimensions
%               'useSlider'         true or false
%                                   provides interactive slider for
%                                   slices/volumes;
%                                   assumes default:    selectedSlices = Inf
%                                                       selectedVolumes = Inf
%               'fixedWithinFigure' determines what dimension is plotted in
%                                   (subplots of) 1 figure
%                                   'slice(s)'    all slices in 1 figure;
%                                   new figure for each volume
%                                   'volume(s)'   all volumes in 1 figurel
%                                   new figure for each slice
%               'colorMap'          string, any matlab colormap name
%                                   e.g. 'jet', 'gray'
%               'colorBar',         'on' or 'off' (default)
%                                   where applicable, determines whether
%                                   colorbar with displayRange shall be plotted
%                                   in figure;
%               'overlayImages'     (cell of) MrImages that will be
%                                   overlayed
%               'overlayMode'       'edge', 'mask', 'map'
%                                   'edge'  only edges of overlay are
%                                           displayed
%                                   'mask'  every non-zero voxel is
%                                           displayed (different colors for
%                                           different integer values, i.e.
%                                           clusters'
%                                   'map'   thresholded map in one colormap
%                                           is displayed (e.g. spmF/T-maps)
%                                           thresholds from
%                                           overlayThreshold
%               'overlayThreshold'  [minimumThreshold, maximumThreshold]
%                                   tresholds for overlayMode 'map'
%                                   default: [-Inf, Inf] = [minValue, maxValue]
%                                   everything below minValue will not be
%                                   displayed;
%                                   everything above maxValue
%                                   will have brightest color
%               'overlayAlpha'      transparency value of overlays
%                                   (0 = transparent; 1 = opaque; default: 0.1)
%
%
% OUT
%   fh          [nFigures,1] vector of figure handles
%
% EXAMPLE
%
%   Y.plot4D('selectedVolumes', [6:10])
%   Y.plot4D('displayRange', [0 1000])
%   Y.plot4D('useSlider', true, 'selectedVolumes', Inf);
%
%   See also

% Author:   Saskia Klein & Lars Kasper
% Created:  2014-05-21
% Copyright (C) 2014 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public Licence (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

% for complex data, plot absolute value per default
if isreal(this)
    defaults.signalPart         = 'all';
else
    defaults.signalPart         = 'abs';
end

defaults.plotType               = 'labeledMontage';
defaults.plotMode               = 'linear';
defaults.selectedVolumes        = 1;
defaults.selectedX              = Inf;
defaults.selectedY              = Inf;
defaults.selectedSlices         = Inf;
defaults.sliceDimension         = 3;
defaults.rotate90               = 0;
defaults.displayRange           = [];
defaults.useSlider              = false;
defaults.fixedWithinFigure      = 'volume';
defaults.colorMap               = 'gray';
defaults.colorBar               = 'off';
defaults.overlayImages          = {};
defaults.overlayMode            = 'mask';
defaults.overlayThreshold       = [];
defaults.overlayAlpha           = 0.1;

args = tapas_uniqc_propval(varargin, defaults);
tapas_uniqc_strip_fields(args);

doPlotColorBar = strcmpi(colorBar, 'on');
doPlotOverlays = any(strcmpi(plotType, {'overlay', 'overlays'})) || ...
    ~isempty(overlayImages);

% slider enables output of all Slices and Volumes per default, strip data
% again under this assumption, if slider is used for display
if useSlider
    defaults.selectedVolumes = Inf;
    defaults.selectedSlices = Inf;
    args = tapas_uniqc_propval(varargin, defaults);
    tapas_uniqc_strip_fields(args);
end

% Assemble parameters for data extraction into one structure
argsExtract = struct('sliceDimension', sliceDimension, ...
    'selectedX', selectedX, 'selectedY', selectedY, ...
    'selectedSlices', selectedSlices, 'selectedVolumes', selectedVolumes, ...
    'plotMode', plotMode, 'rotate90', rotate90, 'signalPart', signalPart);

if isempty(this.data)
    error('tapas:uniqc:MrImage:plot4D:EmptyDataMatrix', ...
        'Data matrix empty for MrImage-object %s', this.name);
end

% retrieve plot data without actually plotting...
if doPlotOverlays
    argsOverlays = struct('sliceDimension', sliceDimension, ...
        'selectedSlices', selectedSlices, 'selectedVolumes', selectedVolumes, ...
        'plotMode', plotMode, 'rotate90', rotate90, 'signalPart', signalPart, ...
        'overlayMode', overlayMode, 'overlayThreshold',  overlayThreshold, ...
        'doPlot', true);

    [fh, dataPlot] = this.plot_overlays(overlayImages, argsOverlays);
    return
else
    if isempty(displayRange)
        [dataPlot, displayRange, resolution_mm] = this.extract_plot4D_data(argsExtract);
    else
        [dataPlot, ~, resolution_mm] = this.extract_plot4D_data(argsExtract);
    end
end

nVolumes = size(dataPlot,4);
nSlices = size(dataPlot,3);

if isinf(selectedSlices)
    selectedSlices = 1:nSlices;
end

if isinf(selectedVolumes)
    selectedVolumes = 1:nVolumes;
end

% slider view
if useSlider
    % useSlider is not a plotType, since it shall be combined with all
    % plot-types (overlays, montages) in a later version of this code

    % tapas_uniqc_slider4d(dataPlot, @(varargin) ...
    %      tapas_uniqc_plot_abs_image(varargin{:}, colorMap), ...
    %     nSlices);

    tapas_uniqc_slider4d(dataPlot, @(Y,iDynSli, fh, yMin, yMax) ...
        tapas_uniqc_plot_abs_image(Y,iDynSli, fh, yMin, yMax, colorMap, colorBar), ...
        nSlices, displayRange(1), displayRange(2), this.name);

    % to also plot phase:
    %    tapas_uniqc_slider4d(dataPlot, @tapas_uniqc_plot_image_diagnostics, ...
    %        nSlices);

else
    switch lower(plotType)
        case {'3d', 'ortho'}
            this.plot3d(argsExtract);
        case {'spm', 'spminteractive', 'spmi'}
            % calls spm_image-function (for single volume) or
            % spm_check_registration (multiple volumes)

            % get current filename, make sure it is nifti-format
            fileName = this.parameters.save.fileName;
            fileNameNifti = fullfile(this.parameters.save.path, ...
                regexprep(fileName, '\..*$', '\.nii'));

            % create nifti file, if not existing
            % TODO: how about saved objects with other file names
            if ~exist(fileNameNifti, 'file')
                this.save(fileNameNifti);
            end

            % select Volumes
            fileNameVolArray = tapas_uniqc_get_vol_filenames(fileNameNifti);

            % display image
            if numel(selectedVolumes) > 1
                spm_check_registration( ...
                    fileNameVolArray{selectedVolumes});
            else
                spm_image('Display', fileNameVolArray{selectedVolumes});
            end

            % delete temporary files for display
            if strcmpi(this.parameters.save.keepCreatedFiles, 'none')

                switch lower(plotType)
                    case {'spminteractive', 'spmi'}
                        input('Press Enter to leave interactive mode');
                end

                delete(fileNameNifti);
                [stat, mess, id] = rmdir(this.parameters.save.path);
            end

            % restore original file name
            this.parameters.save.fileName = fileName;

        case {'montage', 'labeledmontage'}

            if strcmpi(plotType, 'labeledMontage')

                stringLabelSlices = cellfun(@(x) num2str(x), ...
                    num2cell(selectedSlices), 'UniformOutput', false);
                stringLabelVolumes = cellfun(@(x) num2str(x), ...
                    num2cell(selectedVolumes), 'UniformOutput', false);
            else
                stringLabelSlices = [];
                stringLabelVolumes = [];
            end

            switch lower(fixedWithinFigure);
                case {'volume', 'volumes'}
                    for iVol = 1:nVolumes

                        nFrames = size(dataPlot, 3);

                        stringTitle = sprintf('%s - volume %d', this.name, ...
                            selectedVolumes(iVol));
                        fh(iVol,1) = figure('Name', stringTitle, 'WindowStyle', 'docked');

                        tapas_uniqc_labeled_montage(permute(dataPlot(:,:,:,iVol), [1, 2, 4, 3]), ...
                            'DisplayRange', displayRange, ...
                            'LabelsIndices', stringLabelSlices);

                        set(gca, 'DataAspectRatio', abs([resolution_mm(1) resolution_mm(2), 1]));

                        title(tapas_uniqc_str2label(stringTitle));
                        if doPlotColorBar
                            colorbar;
                        end
                        colormap(colorMap);

                    end

                case {'slice', 'slices'}

                    for iSlice = 1:nSlices
                        stringTitle = sprintf('%s - slice %d', this.name, ...
                            selectedSlices(iSlice));
                        fh(iSlice,1) = figure('Name', stringTitle, 'WindowStyle', 'docked');
                        tapas_uniqc_labeled_montage(dataPlot(:,:,iSlice,:), ...
                            'DisplayRange', displayRange, ...
                            'LabelsIndices', stringLabelVolumes);

                        set(gca, 'DataAspectRatio', [resolution_mm(1) resolution_mm(2), 1]);
                        title(tapas_uniqc_str2label(stringTitle));
                        if doPlotColorBar
                            colorbar;
                        end
                        colormap(colorMap);
                    end

            end % fixedWithinFigure
    end % plotType
end % use Slider
end


function obj = addblobs(obj, cl, varargin)
% This is a method for fmridisplay objects that adds blobs to one or more montages and other surface plot(s).
%
% :Usage:
% ::
%
%     obj = addblobs(obj, cl, varargin)
%
% See addthreshblobs and multi_threshold methods for a multiple thresholds version
% render_blobs does most of the hard work.
%
% :Inputs:
%
%   **obj:**
%        an fmridisplay object
%
%   **cl:**
%        a region object. If you're using an fmri_data object pass in region(fmri_data_obj)
%
% :Optional inputs:
%
% There are many optional inputs that control display features of blobs.
% These are determined by render_blobs
%
%   **COLOR:**
%
%   **'color':**
%        followed by color vector, e.g., [0 1 1], for solid-color blobs
%
%   **'maxcolor':**
%        followed by color vector for max color range, e.g., [0 1 1]
%
%   **'mincolor':**
%        followed by color vector for min color range, e.g., [0 0 1]
%
%   **'onecolor':**
%        force solid-color blobs
%
%   **'splitcolor':**
%        Positive and negative values are mapped to different
%        colormaps. Default is +=hot, -=cool colors. Followed
%        optionally by cell array with
%        vectors of 4 colors defining max/min for +/- range,
%        {minnegcolor maxnegcolor minposcolor maxposcolor}
%        e.g., {[0 0 1] [.3 0 .8] [.8 .3 0] [1 1 0]}
%
%   **'indexmap':**
%       Interpret data as indices into colormap. Followed by an n x 3
%       vector of colormap values. Each element of your input data should
%       specify a row of this colormap.
%
%   **'OUTLINING:**
%
%   **''outline'
%
%   **'linewidth':**
%        followed by width value, e.g., 1
%
%        Note: add 'no_surface' to stop updating the existing surface blobs
%
%
%   **'COLOR RANGE:**
%
%   **'cmaprange':**
%        followed by range of values, e.g., [0 40], [-3 3]. Used in
%        color and transparency setting under some circumstances.
%
%   **'TRANSPARENCY:**
%        {'trans', 'transparent','scaledtransparency', 'constanttrans', [val], 'transvalue', [val]}
%
%   **'trans':**
%        Transparent blobs; with no other input, transparency = 0.75 (1 is opaque, 0 is transparent/invisible)
%
%   **'scaledtransparency':**
%        Transparency is a function of voxel value, lower values are more transparent
%
%   **'transvalue':**
%        Followed by width value, e.g., 1. also 'constanttrans'
%
%
% :Other Options:
%
%   **'smooth':**
%        Smooth blobs
%
%   **'contour':**
%
%   **'interp':**
%      Options to pass to interp2 when rendering blobs on standard
%      brain. See help interp2 for valid interpolation methods
%
%   **'no_surface':**
%        Do not add blobs to surface handles, if they exist
%
%   **'noverbose'** : turn off verbose text reporting
%
%   **'depth'** : followed by number (mm) changes search depth (default=2)
%
% CONTROL OF WHICH MONTAGE
%
%   **'wh_montages':**
%        followed by vector of montage numbers as they appear in
%        the list of registered montages in the fmridisplay object
%
% CONTROL OF WHICH SURFACE
%
%   **'wh_surfaces':**
%        followed by vector of surface numbers as they appear in
%                   the list of registered surfaces in the fmridisplay object
%
% :Examples:
% ::
%
%    obj = addblobs(obj, cl, 'color', [0 1 1]);
%    obj = addblobs(obj, cl, 'color', [0 0 1], 'outline');
%    obj = addblobs(obj, cl, 'color', [0 1 0], 'outline', 'linewidth', 1, 'smooth');
%    obj = addblobs(obj, cl, 'color', [1 0 0], 'smooth', 'cmaprange', [0 40]);
%    obj = addblobs(obj, cl, ... 'wh_montages', 1);
%    obj = addblobs(obj, cl, 'splitcolor', ... 'cmaprange', ... 'trans');
%
% Add only to montage 2 in vector of montages in obj.montage
% ::
%
%    obj = addblobs(obj, cl, 'which_montages', 2);
%
% Map values to the colormap red->yellow.
%
% This uses the default percentile-based mapping so that 20% of voxels
% will have the low color and 20% will have the high color, and the rest will be in between:
% ::
%
%    obj = addblobs(obj, cl, 'maxcolor', [1 1 0], 'mincolor', [1 0 0]);
%
% Same, but now Map a specific range of values in image ([0 to .05])
% ::
%
%    obj = addblobs(obj, cl, 'maxcolor', [1 1 0], 'mincolor', [1 0 0], 'cmaprange', [0 .05]);
%
% Separate positive and negative activations and map to a split colormap;
%
% See render_blobs
% ::
%
%    o2 = addblobs(o2, cl, 'splitcolor', {[0 0 1] [.3 0 .8] [.8 .3 0] [1 1 0]}, 'wh_montages', 1);
%
% It is possible to transparency-map values in a statistic image so you
% can show 'unthresholded' statistic values.  e.g.:
% ::
%
%    o2 = addblobs(o2, cl, 'splitcolor', {[0 0 1] [0 1 1] [1 .5 0] [1 1 0]}, 'cmaprange', [-2 2], 'trans', 'scaledtransparency');
%
% ..
%    Copyright Tor Wager, 2011
% ..

% ..
%    Add the volume to activation maps in fmridisplay object
% ..

% Check and convert to region
% -------------------------------------------------------------------
if isstruct(cl) && ~isa(cl, 'region'), cl = cluster2region(cl); end

if isa(cl, 'image_vector'), cl = region(cl); end

if ~isa(cl, 'region')
    error('cl input must be a region object. Try region() constructor method.');
end

if isempty(cl), return, end

% Map to volume space and interpolate
% -------------------------------------------------------------------

[~, mask] = clusters2mask2011(cl); % turn clusters into mask and volume info

if sum(mask(:)) == 0, warning('No voxels in cl! Empty/zero cl.Z field? Bad cl? No results?'); return, end

XYZ = cat(2, cl(:).XYZ);

dim = max(XYZ, [], 2);

V = struct('mat', cl(1).M, 'dim', dim');

SPACE = map_to_world_space(V);

obj.activation_maps{end + 1} = struct('mapdata', mask, 'V', V, 'SPACE', SPACE, 'blobhandles', [], 'cmaprange', [], ...
    'mincolor', [0 0 1], 'maxcolor', [1 0 0], 'color', []);

% Montage selection and options
% -------------------------------------------------------------------

% select which montages; default = all
wh_montage = 1:length(obj.montage);

whm = strcmp(varargin, 'wh_montages') | strcmp(varargin, 'wh_montage') | strcmp(varargin, 'which_montages') | strcmp(varargin, 'which montages');
if any(whm)
    whm = find(whm);
    wh_montage = varargin{whm(1) + 1};
end

% select which surfaces; default = all
wh_surface = 1:length(obj.surface);
addsurfaceblobs = 1;

whs = strcmp(varargin, 'wh_surfaces') | strcmp(varargin, 'wh_surface') | strcmp(varargin, 'which_surfaces') | strcmp(varargin, 'which surfaces');
if any(whs)
    whs = find(whs);
    wh_surface = varargin{whs(1) + 1};
end

% Default color values
% -------------------------------------------------------------------

% default values
dosplitcolor = 1;
doonecolor = 0;
domaxcolor = 0;
domincolor = 0;

maxposcolor = [1 1 0]; % max pos, most extreme values
minposcolor = [1 .4 .5]; % [.8 .3 0]; % min pos
maxnegcolor = [0 .8 .8]; % [.3 .6 .9]; % max neg
minnegcolor = [0 0 1]; % min neg, most extreme values
indexmap = [];

% More purply orange and deeper blue:  {[0 0 1] [.3 0 .8] [.8 .3 0] [1 1 0]}
% more straight orange to yellow, cyan: {[0 0 1] [0 1 1] [1 .5 0] [1 1 0]}

%add_splitcolor_to_varargin = 0; % internal control, not input option
% pos_colormap = colormap_tor([1 0 .5], [1 1 0], [.9 .6 .1]);  %reddish-purple to orange to yellow
% neg_colormap = colormap_tor([0 0 1], [0 1 1], [.5 0 1]);  % cyan to purple to dark blue

depth = 2;

for i = 1:length(varargin)
    if ischar(varargin{i})
        switch varargin{i}

            case {'color', 'onecolor', 'solid'} % many are passed into render_blobs - don't need to do anything
                dosplitcolor = 0;
                 doonecolor = 1;

            case 'maxcolor'
                dosplitcolor = 0;
                 domaxcolor = 1;
                 maxcolor = varargin{i + 1};

            case 'mincolor'
                dosplitcolor = 0;
                 domincolor = 1;
                 mincolor = varargin{i + 1};

            case 'indexmap'
                for exclusive = {'color', 'onecolor', 'solid', 'maxcolor','mincolor','splitcolor'}
                    assert(~contains(exclusive{1},varargin(cellfun(@ischar,varargin))),...
                        sprintf('Cannot evaluate addblobs() with both ''indexmap'' and ''%s'' arguments. These are mutually exclusive',...
                            exclusive{1}));
                end
                dosplitcolor = 0;

                try
                    indexmap = varargin{i+1};
                catch
                    error('''indexmap'' argument must be followed by an n x 3 matrix of colormap values');
                end

            case 'splitcolor'

                if length(varargin) > i && iscell(varargin{i + 1})
                    % we have entered colors

                    splitcolors = varargin{i + 1};
                    if ~iscell(splitcolors) || length(splitcolors) ~= 4
                        error('Enter splitcolor followed by a 4-element cell vector of 4 colors\n{Min_neg} {Max_neg} {Min_pos} {Max_pos}');
                    end
                    maxposcolor = splitcolors{4}; % max pos
                    minposcolor = splitcolors{3}; % min pos
                    maxnegcolor = splitcolors{2}; % max neg
                    minnegcolor = splitcolors{1}; % min neg

                else
                    % use defaults - but add the default colors to varargin
                    % because these are passed on to render_blobs
                    % this will be done below

                end

             case 'depth'
                depth = varargin{i + 1};

            case 'no_surface'
                addsurfaceblobs = 0;

            otherwise %suppress warning because other options passed on.  warning(['Unknown input string option:' varargin{i}]);
        end
    end
end

% Add relevant colors and args to varargin, because we may have passed in
% keywords without following args, intending to use defaults specified above
% These are passed to render_blobs and also used to update legend registry
% in fmridisplay obj

if dosplitcolor

    mysplitcolors = {minnegcolor maxnegcolor minposcolor maxposcolor};

    wh = strcmp(varargin, 'splitcolor');
    varargin(wh) = [];  % remove, add to end
    varargin{end + 1} = 'splitcolor';
    varargin{end + 1} = mysplitcolors;

elseif doonecolor
    % do not edit var args, just pass through

else  % add maxcolor/mincolor to varargin

    if domaxcolor

        wh = strcmp(varargin, 'maxcolor');
        varargin(wh) = [];  % remove, add to end
        varargin{end + 1} = 'maxcolor';
        varargin{end + 1} = maxcolor;

    end

    if domincolor

        wh = strcmp(varargin, 'mincolor');
        varargin(wh) = [];  % remove, add to end
        varargin{end + 1} = 'mincolor';
        varargin{end + 1} = mincolor;

    end

end

% Resampling whole map seems to be too slow: do this in render slice...
% fprintf('Resampling map data to underlay space.');
%
% [resampled_dat, SPACEto] = resample_space(mask, V, obj.SPACE);
%
% fprintf(' Done.\n');
%
% obj.activation_maps{end + 1} = struct('mapdata', resampled_dat, 'V_original', V, 'blobhandles', []);

wh_to_display = length(obj.activation_maps);

% Find valid handles and render blobs on them
% -------------------------------------------------------------------------

currentmap = obj.activation_maps{wh_to_display};

if isempty(currentmap) || ~isfield(currentmap, 'mapdata') || isempty(currentmap.mapdata)

    error('Map to display is not a valid activation map on fmridisplay object.');

end

% Montages
% -------------------------------------------------------------------------

for i = wh_montage

    if length(obj.montage) < i
        error('Requested montage does not exist! Check input montage indices.');
    end

    % render, and return color ranges (splitcolor will change these)
    % Note: mincolor, maxcolor used in setting fields in fmridisplay for legend

    [blobhan, cmaprange, mincolor, maxcolor] = render_blobs(currentmap, obj.montage{i}, obj.SPACE, varargin{:});

    % Register blob handles and colormap-defining range in object
    if ~isempty(blobhan)
        obj.activation_maps{wh_to_display}.blobhandles = [obj.activation_maps{wh_to_display}.blobhandles; blobhan];

        obj.activation_maps{wh_to_display}.cmaprange = cmaprange;

        % update color info, for legend (or use defaults..set in
        % render_blobs)_
        for Arg = {'color'}

            whmax = find(strcmp(varargin, Arg{1}));
            if ~isempty(whmax)
                obj.activation_maps{wh_to_display}.(Arg{1}) = [obj.activation_maps{wh_to_display}.(Arg{1}) varargin{whmax(1) + 1}];
            end

        end

        for Arg = {'mincolor' 'maxcolor'}

            str = (['obj.activation_maps{wh_to_display}.(Arg{1}) = ' Arg{1} ';']);
            eval(str);

        end

    end
end

% Surfaces
% -------------------------------------------------------------------------

if addsurfaceblobs
    for i = wh_surface

        if length(obj.surface) < i
            warning('Requested surface does not exist! Check input surface indices.');
            continue
        end

        % Set color maps for + / - values
        if dosplitcolor || doonecolor || domaxcolor || domincolor
            pos_colormap = colormap_tor(minposcolor, maxposcolor);
            neg_colormap = colormap_tor(minnegcolor, maxnegcolor);
        end

        % OLD method: cluster_surf
        % cluster_surf(cl, depth, 'heatmap', 'colormaps', pos_colormap, neg_colormap, obj.surface{i}.object_handle);

        img = region2imagevec(cl);
        if dosplitcolor
            render_on_surface(img, obj.surface{i}.object_handle, 'pos_colormap', pos_colormap, 'neg_colormap', neg_colormap, varargin{:});
        else
            if isempty(indexmap)
                render_on_surface(img, obj.surface{i}.object_handle, varargin{:});
            else
                render_on_surface(img, obj.surface{i}.object_handle, varargin{:},'colormap', indexmap, 'indexmap');
            end
        end

    end
end

end  % main function


function [nch, npoints, freq, d] = ddt_v(filename)
% ddt_v(filename) Read data from a .ddt file returning samples in mV
%
% [nch, npoints, freq, d] = ddt_v(filename)
%
% INPUT:
%   filename - if empty string, will use File Open dialog
%
% OUTPUT:
%   nch - number of channels
%   npoints - number of data points for each channel
%   freq - A/D frequency
%   d - [nch npoints] data array (in mV)

if nargin < 1
    error 'Expected 1 input argument';
end
if (isempty(filename))
   [fname, pathname] = uigetfile('*.ddt', 'Select a Plexon .ddt file');
   if isequal(fname,0)
     error 'No file was selected'
   end
   filename = fullfile(pathname, fname);
end

[nch, npoints, freq, d] = mexPlex(20, filename);


function a = tocmplx(a)
%TOCMPLX      Type cast to complex interval
%
%   z = tocmplx(a)
%

% written  10/16/98     S.M. Rump
% modified 11/30/98     S.M. Rump  improved speed
% modified 09/02/00     S.M. Rump  same as cintval
%                                  rounding unchanged after use
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 11/20/05     S.M. Rump  fast check for rounding to nearest
% modified 12/03/05     S.M. Rump  obsolete
%

  error('please replace "tocmplx" by "cintval"')


function [x_preds, y_preds] = load_pred_result(mat_folder_path, img_basename)
   % Load pred mat file for each test image from LSP dataset.
   mat_name = strcat(img_basename, '.mat');
   mat_path = strcat(mat_folder_path, '/', mat_name);
   %disp(mat_path);
   pred_struct = load(mat_path);
   x_preds = pred_struct.joints(:, 2);
   y_preds = pred_struct.joints(:, 1);
   %disp(x_preds);
end