function DCM = spm_dcm_phase(DCM)
% Estimate parameters of a DCM model of phase-coupled responses
% FORMAT DCM = spm_dcm_phase(DCM)
%
% DCM
%    name: name string
%       M:  Forward model
%              M.dipfit - leadfield specification
%       xY: data   [1x1 struct]
%       xU: design [1x1 struct]
%
%   Sname: cell of source name strings
%
%   Connection constraints:
%
%       A: {[nr x nr double] }
%       B: {[nr x nr double]}   for GUI specification
%                               (Nfourier=1 & only sine terms)
%   or
%
%       As: [nr x nr x Nfourier]
%       Ac: [nr x nr x Nfourier]
%       Bs: [nr x nr x Nfourier]
%       Bc: [nr x nr x Nfourier]   for script specification
%
%   options.type         - 'ECD'
%__________________________________________________________________________
% Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging
%
% Will Penny
% $Id: spm_dcm_phase.m 4884 2012-09-03 13:33:17Z guillaume $

% check options
%==========================================================================
clear spm_erp_L

% Filename and options
%--------------------------------------------------------------------------
try, DCM.name;                  catch, DCM.name           = 'DCM_PHASE'; end
try, DCM.options.Nmodes;        catch, DCM.options.Nmodes = 4;         end
try, h     = DCM.options.h;     catch, h                  = 1;         end
try, onset = DCM.options.onset; catch, onset              = 80;        end

% Data and spatial model
%==========================================================================
DCM    = spm_dcm_erp_dipfit(DCM, 1);

% Get data if not gotten already
%if ~isfield(DCM.xY,'source')
    DCM  = spm_dcm_phase_data(DCM);
%end

disp('Estimating Model ...');

xY     = DCM.xY;
xU     = DCM.xU;
xU.dt  = xY.dt;

if isfield(DCM,'A')
    % If using UI, copy model structures into As and Bs matrices
    DCM.As=DCM.A{1};
    DCM.Bs{1}=DCM.B{1};
end

% dimensions
%--------------------------------------------------------------------------
Nt     = length(xY.y);                  % number of trials
Nr     = size(DCM.As,1);                % number of sources
nx     = Nr;                            % number of states

Ns     = size(xY.y{1},1);               % number of samples
xU.u   = zeros(Ns,1);

Nu     = size(xU.X,2);                  % number of trial-specific effects

% Set error covariance components - one per region
%--------------------------------------------------------------------------
xY.Q   = spm_Ce(Ns*Nt*ones(1,Nr));

% Offsets
xY.X0  = sparse(Ns,0);

% Inputs
%==========================================================================

% trial-specific effects
%--------------------------------------------------------------------------
try
    if length(DCM.Bs) ~= Nu;
        warndlg({'Please ensure number of trial specific effects', ...
                 'encoded by DCM.xU.X & DCM.B are the same'})
    end
catch
    DCM.Bs = {};
end

% model specification and nonlinear system identification
%==========================================================================
M      = DCM.M;

M.freq = mean(DCM.options.Fdcm);
M.fb = 0.5*(DCM.options.Fdcm(2)-DCM.options.Fdcm(1));

try, M = rmfield(M,'g');  end
try, M = rmfield(M,'FS'); end

if ~isfield(M,'dipfit')
    M.dipfit=[];
end

% prior moments
%--------------------------------------------------------------------------
[pE,gE,pC,gC] = spm_phase_priors(DCM,M.fb,M.dipfit);

% likelihood model
%--------------------------------------------------------------------------
M.IS  = 'spm_gen_phase';
M.f   = 'spm_fx_phase';
M.G   = 'spm_lx_phase';

M.pE  = pE;
M.pC  = pC;
M.gE  = gE;
M.gC  = gC;
M.n   = nx;
M.l   = Nr;
M.ns  = Ns;

% Don't plot progress
try, M.nograph; catch, M.nograph=0; end

% Initial state
try
    M.x;
catch
    M.x=zeros(Nr,1);
end

% Set up initial phases
for n=1:length(DCM.xY.y)
    xx=DCM.xY.y{n}(1,:);
    M.trial{n}.x = double(xx(:)');
end

% keyboard
% myx=spm_gen_phase(pE,M,xU);

% EM: inversion
%--------------------------------------------------------------------------
[Qp,Qg,Cp,Cg,Ce,F] = spm_nlsi_N(M,xU,xY);

% Data ID
%==========================================================================
if isfield(M,'FS')
    try
        ID  = spm_data_id(feval(M.FS,xY.y,M));
    catch
        ID  = spm_data_id(feval(M.FS,xY.y));
    end
else
    ID  = spm_data_id(xY.y);
end

% Bayesian inference {threshold = prior} NB Prior on A,B  and C = exp(0) = 1
%==========================================================================
warning('off','SPM:negativeVariance');
dp  = spm_vec(Qp) - spm_vec(pE);
Pp  = spm_unvec(1 - spm_Ncdf(0,abs(dp),diag(Cp)),Qp);
warning('on','SPM:negativeVariance');

% neuronal and sensor responses (x and y)
%--------------------------------------------------------------------------
x   = feval(M.IS,Qp,M,xU);        % prediction (source space)
L   = feval(M.G, Qg,M);           % get gain matrix

% trial-specific responses (in mode, channel and source space)
%--------------------------------------------------------------------------
for i = 1:Nt
    s    = x{i};                  % prediction (source space)
    y{i} = s*L';                  % prediction (sensor space)
    %r  = xY.y{i} - y;            % residuals  (sensor space)

end

% Change back design matrix to user specified
xU.X=DCM.xU.oldX;

% store estimates in DCM
%--------------------------------------------------------------------------
DCM.M  = M;                    % model specification
DCM.xY = xY;                   % data structure
DCM.xU = xU;                   % input structure
DCM.Ep = Qp;                   % conditional expectation f(x,u,p)
DCM.Cp = Cp;                   % conditional covariances G(g)
DCM.Eg = Qg;                   % conditional expectation
DCM.Cg = Cg;                   % conditional covariances
DCM.Pp = Pp;                   % conditional probability
DCM.Ce = Ce;                   % conditional error covariance
DCM.F  = F;                    % Laplace log evidence
DCM.ID = ID;                   % data ID
DCM.y  = y;                    % Model predictions

% and save
%--------------------------------------------------------------------------
save(DCM.name, 'DCM', spm_get_defaults('mat.format'));
assignin('base','DCM',DCM)


function im = imadjust3(im)
%% imadjust on three channel.

%% License
% ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY
% Copyright (c) 2018 Bingyao Huang
% All rights reserved.

% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:

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

% If you publish results obtained using this software, please cite our paper.

% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.

%%

% enhance color
im(:,:,1) = imadjust(im(:,:,1));
im(:,:,2) = imadjust(im(:,:,2));
im(:,:,3) = imadjust(im(:,:,3));
end


function [Population,fitness] = EnvironmentalSelection(Population,PopObj,OffObj,N)
% The environmental selection of TiGE_1

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    [FrontNo,~] = NDSort([PopObj;OffObj],N);
    fcv = Calculate_fcv(Population); % CV of hybrid population
    fitness = FrontNo' + fcv./(fcv+1);
    [~,index] = sort(fitness);
    Population = Population(index(1:N));
    fitness = fitness(index(1:N));
end


function [ i, j, v ] = find( x )

%Disciplined convex/geometric programming information for FIND:
%   When used in CVX models, FIND cannot deduce the numeric value of a
%   CVX variable. So it returns the indices of elements that are
%   "structurally" nonzero; i.e., that are not *identically* zero.
%   This is similar to the concept of structural nonzeros in sparse
%   matrix factorizations. To illustrate the distinction, consider:
%      variable x(3);
%      x(2) == 0;
%      y = [x(1);0;x(3)];
%   In this case, FIND(x) returns [1;2;3] even though x(2) has been set
%   to zero in an equality constraint. (After all, the overall model may
%   be infeasible, in which case x(2) is arguably not zero.) However,
%   FIND(y) will return [1;3], because y(2) is identically zero.
%
%   When X is a CVX variable, the first two outputs of [I,J,V]=FIND(X)
%   are constant, and the third is a CVX variable containing the
%   structural nonzeros of X.
%
%   FIND(X) places no convexity restrictions on its argument.

ndxs = find( any( x.basis_, 1 ) );
ndxs = ndxs( : );

if nargout > 1,
    i = ndxs - 1;
    j = floor( i / x.size_(1) ) + 1;
    i = rem( i, x.size_(1) ) + 1;
else
	i = ndxs;
end

if nargout > 2,
    v = reshape( cvx_subsref( x, ndxs ), length( ndxs ) );
end

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function h = makemovie(matrix, cmap)
% h = makemovie(matrix, cmap)
h=figure;
% Resize the figure window to size of movie required.
% 3) Record the size of the plot window:
winsize = get(h,'Position');
% 4) Adjust size of this window to include the whole figure window (if you require the axes, title and axis labels
%      in the movie):
winsize(1:2) = [0 0];
% 5) Set the number of frames:
numframes=size(matrix,3);
% 6) Create the MATLAB movie matrix:
A=moviein(numframes,h,winsize);
% 7) Fix the features of the plot window (ensures each frame of the movie
% is the same size):
set(h,'NextPlot','replacechildren')
% 8) Within a loop, plot each picture and save to MATLAB movie matrix:
for i=1:numframes
   imagesc(matrix(:,:,i)); % plot command
   set (gca, 'DataAspectRatio',[1 1 1]);
   if exist ('cmap', 'var')
       colormap(cmap);
   end
   % add axis label, legends, titles, etc. in here
   A(:,i)=getframe(h,winsize);
end
% This procedure creates a movie stored in a special format that is only readable in MATLAB. The first thing you will want to do is to play the movie:
movie(h,A,30,3,winsize)


function lambda = parlett_eigenvalues ( )

%*****************************************************************************80
%
%% PARLETT_EIGENVALUES returns the eigenvalues of the PARLETT matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real LAMBDA(100,1), the eigenvalues.
%
  n = 100;
  lambda = zeros ( n, 1 );

  for i = 1 : n
    lambda(i,1) = i;
  end

  return
end


function results = PTKDivideVolumeIntoSlices(region_mask, dimension, reporting)
    % PTKDivideVolumeIntoSlices. Divides an image volume into a number of thick slices
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2014.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.

    [xc_mm, yc_mm, zc_mm] = region_mask.GetDicomCoordinates;
    midpoint_mm = [min(xc_mm(:)) + max(xc_mm(:)), min(yc_mm(:)) + max(yc_mm(:)), min(zc_mm(:)) + max(zc_mm(:))]/2;
    bounds = region_mask.GetBounds;
    coord_voxel_length_mm = region_mask.VoxelSize(dimension);

    % Get all values of coordinate between min and maximum values
    switch dimension
        case PTKImageOrientation.Axial
            coord_values = bounds(5) : bounds(6);
            coords = zc_mm;
        case PTKImageOrientation.Coronal
            coord_values = bounds(1) : bounds(2);
            coords = yc_mm;
        case PTKImageOrientation.Sagittal
            coord_values = bounds(3) : bounds(4);
            coords = xc_mm;
        otherwise
            reporting.Error('PTKDivideLungsIntoAxialBins:UnsupportedOrientation', 'The orientation was not recognised');
    end

    coord_values_mm = coords(coord_values);

    lung_base_mm = min(coord_values_mm) - coord_voxel_length_mm/2;
    lung_top_mm = max(coord_values_mm) + coord_voxel_length_mm/2;

    coord_offsets_for_all_voxels_mm = coords - lung_base_mm;

    % Compute the coordinates of the boundaries between bins
    bin_size_mm = 16;

    bin_locations = lung_base_mm + bin_size_mm/2 : bin_size_mm : lung_top_mm - bin_size_mm/2;
    bin_distance_from_base = bin_locations - lung_base_mm;

    % Compute bin numbers for each k coordinate
    bin_number = uint8(1 + max(0, floor(coord_offsets_for_all_voxels_mm/bin_size_mm)));

    switch dimension
        case PTKImageOrientation.Axial
            bin_matrix = repmat(shiftdim(bin_number, -2), region_mask.ImageSize(1), region_mask.ImageSize(2));
        case PTKImageOrientation.Coronal
            bin_matrix = repmat(bin_number, [1, region_mask.ImageSize(2), region_mask.ImageSize(3)]);
        case PTKImageOrientation.Sagittal
            bin_matrix = repmat(shiftdim(bin_number, -1), [region_mask.ImageSize(1), 1, region_mask.ImageSize(3)]);
        otherwise
            reporting.Error('PTKDivideLungsIntoAxialBins:UnsupportedOrientation', 'The orientation was not recognised');
    end

    bin_image_raw = bin_matrix.*uint8(region_mask.RawImage);
    bin_image = region_mask.BlankCopy;
    bin_image.ChangeRawImage(bin_image_raw);
    bin_image.ImageType = PTKImageType.Colormap;

    regions = PTKRegionDefinition.empty;
    for bin_index = 1 : numel(bin_distance_from_base)
        coordinates = PTKPoint(midpoint_mm(1), midpoint_mm(2), midpoint_mm(3));
        coordinates = PTKPoint.SetCoordinate(coordinates, dimension, bin_locations(bin_index));
        regions(bin_index) = PTKRegionDefinition(bin_index, bin_index, bin_distance_from_base(bin_index), coordinates);
    end

    results = [];
    results.BinImage = bin_image;
    results.BinRegions = regions;
end


function TorqueOverTime(nlp, sys)

    domains = sys.Gamma.Nodes.Domain;
    T  = SymVariable('t',[2, 1]);
    for i=1:numel(domains)
        domain = domains{i};

        u = domain.Inputs.Control.u;
        u2r = tovector(norm(u).^2)./(T(2)-T(1));
        u2r_fun = SymFunction(['torqueOverTime_' sys.Gamma.Nodes.Name{i}],u2r,{u,T});
        rs_phase = getPhaseIndex(nlp,sys.Gamma.Nodes.Name{i});
        addRunningCost(nlp.Phase(rs_phase),u2r_fun,{'u', 'T'});

    end
    nlp.update;

end


classdef ChRotatorForFiberHomogenizer < handle

    methods (Access = public)

        function Ch = rotate(obj, dir,Ch)
            angle  = obj.computeRotationAngle(dir);
            dir    = obj.computeZdirection();
            C      = obj.makeChTensor(Ch);
            Ch = Rotator.rotate(C,angle,dir);
        end

    end

    methods (Access = private, Static)

         function angle = computeRotationAngle(dir)
            fiberDirection = dir.getValue;
            angle = -acos(dot(fiberDirection,[1 0 0]));
        end

        function C = makeChTensor(Ch)
            C = SymmetricFourthOrderPlaneStressVoigtTensor();
            C.setValue(Ch);
        end

        function dir = computeZdirection()
            d = [ 0 0 1];
            dir = Vector3D;
            dir.setValue(d);
        end

    end
end


%%***************************************************************
%% linsysolve: solve linear system to get dy, and direction
%%             corresponding to unrestricted variables.
%%
%% [xx,coeff,L,resnrm] = linsysolve(schur,UU,Afree,EE,rhs);
%%
%% child functions: symqmr.m, mybicgstable.m, linsysolvefun.m
%%
%% SDPT3: version 3.1
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last Modified: 16 Sep 2004
%%***************************************************************

   function [xx,coeff,L,resnrm] = linsysolve(par,schur,UU,Afree,EE,rhs);

    global solve_ok existspcholsymb exist_analytic_term
    global nnzmat nnzmatold matfct_options matfct_options_old use_LU
    global Lsymb msg diagR diagRold perturb_opt

    spdensity  = par.spdensity;
    printlevel = par.printlevel;
    iter       = par.iter;

    m = length(schur);
    if (iter==1);
       use_LU = 0; matfct_options_old = '';
       diagR = ones(m,1); perturb_opt = 1;
    end
    if isempty(nnzmatold); nnzmatold = 0; end
    diagRold = diagR;
%%
%% schur = schur + rho*diagschur + lam*AAt
%%
    diagschur = full(abs(diag(schur)));
    if (min(diagR) < 1e-6) & (max(diagR) > 1e-2);
       perturb_opt = 2;
    end
    if (perturb_opt == 2) & (iter > 10)
       pertdiag = min(1e-2,1e-15*max(1,diagschur)./max(1e-12,diagR));
       idx = find(diagschur < 1e-6);
       if (norm(rhs(idx)) < 1e-6) & (max(diagschur) > 1e-2)
          pertdiag(idx) = 1e6*ones(length(idx),1);
       end
       mexschurfun(schur,pertdiag);
       if (printlevel); fprintf('*'); end
    else
       diagschur = max(0,full(diag(schur)));
       minrho(1) = max(1e-15, 1e-6/3.0^iter);
       minlam(1) = max(1e-10, 1e-4/2.0^iter);
       minrho(2) = max(1e-04, 1/1.5^iter);
       rho = min(minrho(1),minrho(2)*(1+norm(rhs))/(1+norm(diagschur.*par.y)));
       lam = min(minlam(1),0.1*rho*norm(diagschur)/par.normAAt);
       if (exist_analytic_term); rho = 0; end
       mexschurfun(schur,rho*diagschur);
       mexschurfun(schur,lam*par.AAt);
       %%if (printlevel); fprintf(' %2.1e %2.1e ',rho,lam); end
    end
%%
%% assemble coefficient matrix
%%
    len = size(Afree,2);
    if ~isempty(EE)
       EE(:,[1 2]) = len + EE(:,[1 2]); %% adjust for ublk
    end
    EE = [(1:len)' (1:len)' zeros(len,1); EE];
    if isempty(EE)
       coeff.mat22 = [];
    else
       coeff.mat22 = spconvert(EE);
    end
    coeff.mat12 = [Afree, UU];
    coeff.mat11 = schur; %% important to use perturbed schur matrix
    ncolU = size(coeff.mat12,2);
%%
%% pad rhs with zero vector
%% decide which solution methods to use
%%
    rhs = [rhs; zeros(m+ncolU-length(rhs),1)];
    if (ncolU > 300); use_LU = 1; end
%%
%% Cholesky factorization
%%
    L = []; resnrm = []; xx = inf*ones(m,1);
    if (~use_LU)
       solve_ok = 1;  solvesys = 1;
       nnzmat = mexnnz(coeff.mat11);
       nnzmatdiff = (nnzmat ~= nnzmatold);
       if (nnzmat > spdensity*m^2) | (m < 500)
          matfct_options = 'chol';
       else
          if (par.matlabversion < 7.3)
             matfct_options = 'spchol';
	  else
             matfct_options = 'spcholmatlab';
          end
       end
       if (printlevel>2); fprintf(' %s',matfct_options); end
       if strcmp(matfct_options,'chol')
          if issparse(schur); schur = full(schur); end;
          if (iter<=5); %% to fix strange anonmaly in Matlab
             mexschurfun(schur,1e-20,2);
          end
          L.matfct_options = 'chol';
          L.perm = [1:m];
          [L.R,indef] = chol(schur);
          diagR = diag(L.R).^2;
          %%semilogy(diagschur,'*'); hold on;
          %%semilogy(diagR,'or'); hold off; pause(0.1);
          if (indef)
             diagR = diagRold;
 	     solve_ok = -2; solvesys = 0;
             msg = 'linsysolve: Schur complement matrix not pos. def.';
             if (printlevel); fprintf('\n  %s',msg); end
          end
       elseif strcmp(matfct_options,'spcholmatlab')
          if ~issparse(schur); schur = sparse(schur); end;
          L.matfct_options = 'spcholmatlab';
          [L.R,indef,L.perm] = chol(schur,'vector');
          L.Rt = L.R';
          %%diagR(L.perm(1:length(L.R)),1) = diag(L.R).^2;
          if (indef)
             diagR = diagRold;
 	     solve_ok = -2; solvesys = 0;
             msg = 'linsysolve: Schur complement matrix not pos. def.';
             if (printlevel); fprintf('\n  %s',msg); end
          end
       elseif strcmp(matfct_options,'spchol')
          if ~issparse(schur), schur = sparse(schur); end;
          if (nnzmatdiff | ~strcmp(matfct_options,matfct_options_old))
             [Lsymb,flag] = symbcholfun(schur,par.cachesize);
             if (flag)
                solve_ok = -2;  solvesys = 0;
                existspcholsymb = 0;
                msg = 'linsysolve: symbolic factorization fails';
                if (printlevel); fprintf('\n  %s',msg); end
                use_LU = 1;
             else
                existspcholsymb = 1;
             end
          end
          if (existspcholsymb)
             L = sparcholfun(Lsymb,schur);
             L.matfct_options  = 'spchol';
             L.d(find(L.skip)) = 1e20;
             if any(L.skip) & (ncolU)
                solve_ok = -3; solvesys = 0;
                existspcholsymb = 0;
                use_LU = 1;
                if (printlevel)
                   fprintf('\n  L.skip exists but ncolU > 0.');
                   fprintf('\n  switch to LU factor.');
                end
             end
          end
       end
       if (solvesys)
          if (ncolU)
             tmp = coeff.mat12'*linsysolvefun(L,coeff.mat12)-coeff.mat22;
	     if issparse(tmp); tmp = full(tmp); end
             tmp = 0.5*(tmp + tmp');
             [L.Ml,L.Mu,L.Mp] = lu(tmp);
             tol = 1e-16;
             idx = find(abs(diag(L.Mu)) < tol);
             if ~isempty(idx) & (printlevel); fprintf('**'); end
          end
          [xx,resnrm,solve_ok] = symqmr(coeff,rhs,L);
          if (solve_ok<=0) & (printlevel)
             fprintf('\n  warning: symqmr fails: %3.1f.',solve_ok);
          end
       end
       if (solve_ok < 0)
          if (m < 5000 & strcmp(matfct_options,'chol')) | ...
             (m < 1e5 & strcmp(matfct_options,'spchol')) | ...
             (m < 1e5 & strcmp(matfct_options,'spcholmatlab'))
             use_LU = 1;
             if (printlevel); fprintf('\n  switch to LU factor.'); end
          end
       end
    end
%%
%% LU factorization
%%
    if (use_LU)
       nnzmat = mexnnz(coeff.mat11)+mexnnz(coeff.mat12);
       nnzmatdiff = (nnzmat ~= nnzmatold);
       solve_ok = 1; solvesys = 1;
       if ~isempty(coeff.mat22)
          raugmat = [coeff.mat11, coeff.mat12; coeff.mat12', coeff.mat22];
       else
          raugmat = coeff.mat11;
       end
       if (nnzmat > spdensity*m^2) | (m+ncolU < 500)
          matfct_options = 'lu';
       else
          matfct_options = 'splu';
       end
       if (printlevel > 2); fprintf(' %s ',matfct_options); end
       if strcmp(matfct_options,'lu')
          if issparse(raugmat); raugmat = full(raugmat); end
          [L.l,L.u,L.p] = lu(raugmat);
          L.matfct_options = 'lu';
          L.p = sparse(L.p);
          idx = find(abs(diag(L.u)) < 1e-20);
          if ~isempty(idx)
             msg = 'linsysolve: matrix is singular';
             if (printlevel); fprintf('\n  %s',msg); end
             solvesys = 0;
          end
          [ii,jj] = find(L.p); [dummy,idx] = sort(ii); L.perm = jj(idx);
       end
       if strcmp(matfct_options,'splu')
          if ~issparse(raugmat); raugmat = sparse(raugmat); end
          if (nnzmatdiff | ~strcmp(matfct_options,matfct_options_old))
             Lsymb.perm = symamd(raugmat);
          end
          L.perm = Lsymb.perm;
          L.matfct_options = 'splu';
          if (par.matlabversion >= 6.5)
             [L.l,L.u,L.p,L.q] = lu(raugmat(L.perm,L.perm));
          else
             [L.l,L.u,L.p] = lu(raugmat(L.perm,L.perm));
             L.q = speye(length(raugmat));
          end
       end
       if (solvesys)
          [xx,resnrm,solve_ok] = mybicgstab(coeff,rhs,L,[],[],printlevel);
          if (solve_ok<=0) & (printlevel)
             fprintf('\n  warning: bicgstab fails: %3.1f,',solve_ok);
          end
       end
    end
    if (printlevel>=3); fprintf(' %2.0d',length(resnrm)-1); end
%%
    nnzmatold = nnzmat; matfct_options_old = matfct_options;
%%***************************************************************


settings.ptype = 'MACRO';
% settings.filename = 'CantileverBeam_Triangle_Linear_Fine';
% settings.filename = 'topopt_quad';
% settings.filename = 'GrippingNew';
% settings.ptype = 'MICRO';
% settings.filename = 'RVE_Square_Triangle';
% settings.filename = 'RVE_Square_Triangle_Fine';

settings.method = 'SIMPALL';
%settings.method = 'SIMP_P3';
%settings.method = 'SIMP_Adaptative';

settings.material = 'ISOTROPIC';
settings.initial_case = 'full';
% settings.initial_case = 'circle';
% settings.initial_case = 'horizontal';
% settings.initial_case = 'square';
% settings.initial_case = 'feasible';
% settings.initial_case = 'rand';

settings.cost = {'compliance';'perimeter'}; %'chomog_fraction';'compliance';'perimeter';'chomog_alphabeta';'nonadjoint_compliance';
% settings.weights = []; %all 1
settings.weights = [1 0.1]; %compl+lambda*perimeter
settings.constraint = {'volumeConstraint'};

settings.optimizer = 'SLERP';
%settings.optimizer = 'PROJECTED GRADIENT';settings.incrementFactor = 1;
%settings.optimizer = 'MMA';
%settings.optimizer = 'IPOPT';

settings.filterType = 'P1';
%settings.filter = 'PDE';

settings.TOL.rho_plus = 1;
settings.TOL.rho_minus = 0;
settings.TOL.E_plus = 1;
settings.TOL.E_minus = 1e-3;
settings.TOL.nu_plus = 1/3;
settings.TOL.nu_minus = 1/3;

settings.nsteps = 1;
settings.Vfrac_final = settings.target_parameters.Vfrac;
settings.optimality_final = settings.target_parameters.optimality_tol;
settings.constr_final = settings.target_parameters.constr_tol;
settings.Vfrac_initial = 1;

settings.optimality_initial = 1e-3;
settings.constr_initial = 1e-3;

settings.micro.alpha = [1 1 0]';
settings.micro.beta = [1 1 0]';


report_this_filefun(mfilename('fullpath'));

clear a1 a2 a3 a4 a5
a1=zeros(size(newt2));
a2=zeros(size(newt2));
a3=zeros(size(newt2));
a4=zeros(size(newt2));
a5=zeros(size(newt2));
a6=zeros(size(newt2));
bins=160
c1=0.9;
c2=0.9;
c3=0.9;
a1=newt2;
nmb=sum(a1(:,6)==0);
n=size(a1,1);
str1=['Anteil mit Mb=0: ' num2str(nmb/n*100) '%'];
disp(str1)

disp(' ')
exfig=figure_exists('Mb=f(Ms)',0);

if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Mb=f(Ms)',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end

hold on
[p,r]=corrmbms2(a1(:,10),a1(:,6),1,'Ms','Mb');
hold off

a2=a1;

for i=1:size(a2,1)
    if and(a2(i,6)==0,not(a2(i,10)==0));
        a2(i,6)=round(10*(a2(i,10)*p(1)+p(2)))/10;
        a4(i,1)=a2(i,6);
    end
end

nmb=sum(a2(:,6)==0);
n=size(a2,1);
str1=['Anteil mit Mb=0: ' num2str(nmb/n*100) '%'];
disp(str1)
disp(' ')

for i=1:size(a2,1)
    if a2(i,11)>10;
        a2(i,11)=0;
    end
end

exfig=figure_exists('Mb=f(???)',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits('Name','Mb=f(???)',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end

hold on
[p,r]=corrmbms2(a2(:,11),a2(:,6),1,'???','mb');
hold off

a3=a2;

for i=1:size(a3,1)
    if and(a3(i,6)==0,not(a3(i,11)==0));
        a3(i,6)=round(10*(a3(i,11)*p(1)+p(2)))/10;
        a5(i,1)=a3(i,6);
    end
end

nmb=sum(a3(:,6)==0);
n=size(a3,1);
str1=['Anteil mit Mb=0: ' num2str(nmb/n*100) '%'];
disp(str1)
disp(' ')
disp('Unbenutzbare Eintr�ge')
str1=num2str(sum((a.Magnitude==0&a(:,10)==0)&a(:,11)==0)+sum((a.Magnitude==0&a(:,10)==0)&a(:,11)>10));
disp(str1)

bins=0.05:.1:9;

exfig=figure_exists('Mb Histogram',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Mb Histogram',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end
clf
%subplot(2,3,1)
lo=not(a1(:,6)==0);
ah=a1(lo,:);
bar(bins, histc(ah(:,6),bins))
Xlim([1 9.5])
Xlabel('Mb')

exfig=figure_exists('Ms Histogram',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Ms Histogram',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end
clf
%subplot(2,3,2)
lo=a1(:,6)==0&not(a1(:,10)==0);
ah=a1(lo,:);
bar(bins, histc(ah(:,10),bins))
Xlim([1 9.5])
Xlabel('Ms')

exfig=figure_exists('Mu Histogram',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Mu Histogram',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end
clf
%subplot(2,3,3)
lo=a2(:,6)==0&a2(:,10)==0&not(a2(:,11)==0);
ah=a1(lo,:);
bar(bins, histc(ah(:,11),bins))
Xlim([1 9.5])
Xlabel('Mu')

exfig=figure_exists('Mb + Histogram',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Mb + Histogram',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end
clf
%subplot(2,3,4)
bar( bins,histc(a3(:,6),bins))
Xlim([1 9.5])
Xlabel('Mb +')

exfig=figure_exists('Mb aus Ms Histogram',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Mb aus Ms Histogram',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end
clf
%subplot(2,3,5)
bar( bins,histc(a4(:,1),bins))
Xlabel('Mb aus Ms')
Xlim([1 9.5])

exfig=figure_exists('Mb aus Mu Histogram',0);
if exfig==0
    ui=figure_w_normalized_uicontrolunits( 'Name','Mb aus Mu Histogram',...
        'NumberTitle','off');
    figure_w_normalized_uicontrolunits(ui)
end
clf
%subplot(2,3,6)
bar( bins,histc(a5(:,1),bins))
Xlabel('Mb aus Mu')
Xlim([1 9.5])

%a1=a3;
%clear('a2')
%clear('a3')


function model = yalmip2cbc(interfacedata)

F_struc = interfacedata.F_struc;
Q       = interfacedata.Q;
c       = interfacedata.c;
K       = interfacedata.K;
lb      = full(interfacedata.lb);
ub      = full(interfacedata.ub);
x0      = interfacedata.x0;

if isempty(F_struc)
    Aeq = [];
    beq = [];
    A = [];
    b = [];
else
    Aeq = -F_struc(1:1:K.f,2:end);
    beq = F_struc(1:1:K.f,1);
    A =-F_struc(K.f+1:end,2:end);
    b = F_struc(K.f+1:end,1);
end

ivars = repmat('C',length(c),1);
ivars(interfacedata.integer_variables) = 'I';
ivars(interfacedata.binary_variables) = 'B';

% CBC merges equalities and equalities
ru = full([beq;b]);
rl = full([beq;repmat(-inf,length(b),1)]);
A = [Aeq;A];

% SOS currently not supported
sos.type='';
sos.index=[];
sos.weight=[];

model.f = full(c);
model.A = A;
model.rl = rl;
model.ru = ru;
model.lb = lb;
model.ub = ub;
model.xtype = ivars;
model.sos = sos;
model.x0 = [];
model.H = [];


function plotAmps(vw, scans)
%
% plotAmps(vw)
%
% Bar plot of the amplitudes for each scan, averaging across
% all pixels (in all slices) in the current ROI.
%
% gmb   5/25/98
% jw    6/7/08 added std to user data

% Compute means across scans, for all pixels in the
% currently selected ROI.
if exist('scans', 'var')
    [meanAmps,meanPhs,seAmps,meanStd] = vectorMeans(vw, scans);
else
    [meanAmps,meanPhs,seAmps,meanStd] = vectorMeans(vw);
end
selectGraphWin

% Header
ROIname     = vw.ROIs(vw.selectedROI).name;
headerStr   = ['Mean of amplitudes, ROI ',ROIname];
set(gcf,'Name',headerStr);

% Plot the bar graph
clf
fontSize = 14;
meanAmps
meanStd

mybar(meanAmps,meanStd);
xlabel('Scan','FontSize',fontSize);
ylabel('Mean Amplitude','FontSize',fontSize);
ylim =get(gca,'YLim');
set(gca,'YLim',ylim*1.1);
set(gca,'FontSize',fontSize);

% Save the data in gca('UserData')
data.y = meanAmps;
data.s = meanStd;
set(gca,'UserData',data);


function tapas_hgf_categorical_plotTraj(r)
% Plots trajectories estimated by fitModel for the hgf_categorical perceptual model
% Usage:  est = tapas_fitModel(responses, inputs); tapas_hgf_plotTraj(est);
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2012-2013 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/>.

% Check whether we have a configuration structure
if ~isfield(r,'c_prc')
    error('tapas:hgf:ConfigRequired', 'Configuration required: before calling tapas_hgf_categorical_plotTraj, tapas_hgf_categorical_config has to be called.');
end

% Number of outcomes
no = r.c_prc.n_outcomes;

% Define colors
colors = [1 0 0; 0.67 0 1; 0 0.67 1; 0.67 1 0];

% Set up display
scrsz = get(0,'screenSize');
outerpos = [0.2*scrsz(3),0.2*scrsz(4),0.8*scrsz(3),0.8*scrsz(4)];
figure(...
    'OuterPosition', outerpos,...
    'Name','HGF trajectories');

% Number of trials
t = size(r.u,1);

% Optional plotting of standard deviations (true or false)
plotsd2 = true;
plotsd3 = true;

% Subplots
subplot(3,1,1);

if plotsd3 == true
    upper3prior = r.p_prc.mu3_0 +sqrt(r.p_prc.sa3_0);
    lower3prior = r.p_prc.mu3_0 -sqrt(r.p_prc.sa3_0);
    upper3 = [upper3prior; r.traj.mu(:,3)+sqrt(r.traj.sa(:,3))];
    lower3 = [lower3prior; r.traj.mu(:,3)-sqrt(r.traj.sa(:,3))];

    plot(0, upper3prior, 'ob', 'LineWidth', 1);
    hold all;
    plot(0, lower3prior, 'ob', 'LineWidth', 1);
    fill([0:t, fliplr(0:t)], [(upper3)', fliplr((lower3)')], ...
         'b', 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
end
plot(0:t, [r.p_prc.mu3_0; r.traj.mu(:,3)], 'b', 'LineWidth', 2);
hold all;
plot(0, r.p_prc.mu3_0, 'ob', 'LineWidth', 2); % prior
xlim([0 t]);
title('Posterior expectation \mu_3 of log-volatility of tendency x_3', 'FontWeight', 'bold');
xlabel('Trial number');
ylabel('\mu_3');

subplot(3,1,2);
if plotsd2 == true
    for j=1:no
    upper2prior = r.p_prc.mu2_0(j) +sqrt(r.p_prc.sa2_0(j));
    lower2prior = r.p_prc.mu2_0(j) -sqrt(r.p_prc.sa2_0(j));
    upper2 = [upper2prior; r.traj.mu(:,2,j)+sqrt(r.traj.sa(:,2,j))];
    lower2 = [lower2prior; r.traj.mu(:,2,j)-sqrt(r.traj.sa(:,2,j))];

    plot(0, upper2prior, 'o', 'Color', colors(j,:), 'LineWidth', 1);
    hold all;
    plot(0, lower2prior, 'o', 'Color', colors(j,:), 'LineWidth', 1);
    fill([0:t, fliplr(0:t)], [(upper2)', fliplr((lower2)')], ...
         colors(j,:), 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
    end
end
for j=1:no
    plot(0:t, [r.p_prc.mu2_0(j); r.traj.mu(:,2,j)], 'Color', colors(j,:), 'LineWidth', 2);
    hold all;
    plot(0, r.p_prc.mu2_0(j), 'o', 'Color', colors(j,:), 'LineWidth', 2); % prior
end
xlim([0 t]);
title('Posterior expectations \mu_2 of tendencies x_2', 'FontWeight', 'bold');
xlabel({'Trial number', ' '}); % A hack to get the relative subplot sizes right
ylabel('\mu_2');
hold off;

subplot(3,1,3);
for j=1:no
    plot(0:t, [tapas_sgm(r.p_prc.mu2_0(j), 1); tapas_sgm(r.traj.mu(:,2,j), 1)], 'Color', colors(j,:), 'LineWidth', 2);
    hold all;
    plot(0, tapas_sgm(r.p_prc.mu2_0(j), 1), 'o', 'Color', colors(j,:), 'LineWidth', 2); % prior
end
u = r.u(:,1);
for j=1:no
    plot(find(u==j), -0.08*ones([1 length(find(u==j))]), '.', 'Color', colors(j,:)); % inputs
end
if ~isempty(find(strcmp(fieldnames(r),'y'))) && ~isempty(r.y)
    y = r.y(:,1);
    if ~isempty(find(strcmp(fieldnames(r),'irr')))
        y(r.irr) = NaN; % weed out irregular responses
        plot(r.irr,  1.08.*ones([1 length(r.irr)]), 'x', 'Color', [1 0.7 0], 'Markersize', 11, 'LineWidth', 2); % irregular responses
    end
    for j=1:no
        plot(find(y==j), 1.08*ones([1 length(find(y==j))]), '.', 'Color', colors(j,:)); % responses
    end
    title(['Response y (top dot row), input u (bottom dot row), and posterior probability of outcomes s(\mu_2) for \kappa=', ...
           num2str(r.p_prc.ka), ', \omega=', num2str(r.p_prc.om), ', \vartheta=', num2str(r.p_prc.th)], ...
          'FontWeight', 'bold');
    ylabel('y, u, s(\mu_2)');
    axis([0 t -0.1 1.15]);
else
    title(['Input u (bottom dot row) and posterior probability of outcomes s(\mu_2) for \kappa=', ...
           num2str(r.p_prc.ka), ', \omega=', num2str(r.p_prc.om), ', \vartheta=', num2str(r.p_prc.th)], ...
      'FontWeight', 'bold');
    ylabel('u, s(\mu_2)');
    axis([0 t -0.1 1.1]);
end
plot(1:t, 0.5, 'k');
xlabel('Trial number');
hold off;


%io_loadspec_bruk.m
%Chathura Kumaragamage, McGill University 2016.
%Jamie Near, McGill University 2016.
%
% USAGE:
% [out,ref]=io_loadspec_bruk(filename);
%
% DESCRIPTION:
% Reads in Bruker MRS data (fid.raw, fid.ref).
%
% op_loadspec_bruk outputs the data in structure format, with fields corresponding to time
% scale, fids, frequency scale, spectra, and header fields containing
% information about the acquisition.  The resulting matlab structure can be
% operated on by the other functions in this MRS toolbox.
%
% INPUTS:
% inDir   = Path to the scan number directory that contains the 'pdata' folder.
%
% OUTPUTS:
% out = Input dataset in FID-A structure format.
% ref = The Reference scan data (navigator echoes) in FID-A structure
%       format, if applicable.

function [out,ref]=io_loadspec_bruk(inDir)

%%%%%%%%chathu mod starts

%get the original number of Repetitions (all repatitions from scanner is generated as
%a 1D vector. Need to split before further processing
averages=1; %Because Bruker does the averaging online.
ADC_OFFSET=70;      %(offset between ADC on and ADC acquire, empirically determined)
method_fid=fopen([inDir '/method']);
line=fgets(method_fid);
index=findstr(line,'$PVM_DigNp=');
while isempty(index)
    line=fgets(method_fid);
    index=findstr(line,'$PVM_DigNp=');
end
equals_index=findstr(line,'=');
rawDataPoints=line(equals_index+1:end);
rawDataPoints=str2double(rawDataPoints);
fclose(method_fid);

%NOW LOAD IN THE RAW DATA.  FIRST TRY USING THE FID.RAW FILE.  IF THAT DOES
%NOT WORK, THEN USE THE REGULAR FID FID.
try
    fid_data=fread(fopen([inDir '/fid.raw']),'int');
    real_fid = fid_data(2:2:length(fid_data));
    imag_fid = fid_data(1:2:length(fid_data));
    fids_raw=real_fid-1i*imag_fid;

    method_fid=fopen([inDir '/method']);
    line=fgets(method_fid);
    index=findstr(line,'$PVM_NAverages=');
    while isempty(index)
        line=fgets(method_fid);
        index=findstr(line,'$PVM_NAverages=');
    end
    equals_index=findstr(line,'=');
    rawAverages=line(equals_index+1:end);
    rawAverages=str2double(rawAverages);
    fclose(method_fid);
    fids_raw=reshape(fids_raw,[],rawAverages);
    fids_trunc=fids_raw(ADC_OFFSET:end,:);
    %         fids_trunc=fids_trunc';
    fids=padarray(fids_trunc, [ADC_OFFSET-1,0],'post');
    specs=fftshift(ifft(fids,[],1),1);
    sz=size(specs);
    out.flags.averaged=0;
    %specify the dims
    dims.t=1;
    dims.coils=0;
    dims.averages=2;
    dims.subSpecs=0;
    dims.extras=0;
catch
    %NOW TRY USING FID FILE
    display('WARNING: /fid.raw not found. Using /fid ....')
    %specs=fread(fopen([inDir '/pdata/1/2dseq']),'int');
    fid_data=fread(fopen([inDir '/fid']),'int');
    real_fid = fid_data(2:2:length(fid_data));
    imag_fid = fid_data(1:2:length(fid_data));
    fids_raw=real_fid-1i*imag_fid;

    rawAverages=size(real_fid,1)./rawDataPoints;

    if mod(size(real_fid,1),rawDataPoints) ~=0
        display 'number of repetitions cannot be accurately found';
    end
    fids_raw=reshape(fids_raw,rawDataPoints,[]);

    fids_trunc=fids_raw(ADC_OFFSET:end,:);
    fids=padarray(fids_trunc, [ADC_OFFSET-1,0],'post');
    %convert back to time domain
    %if the length of Fids is odd, then you have to do a circshift of one to
    %make sure that you don't introduce a small frequency shift into the fids
    %vector.
    specs=fftshift(ifft(fids,[],1),1);

    %calculate the size;
    sz=size(specs);
    out.flags.averaged=1;
    %specify the dims
    dims.t=1;
    dims.coils=0;
    dims.averages=0;
    dims.subSpecs=0;
    dims.extras=0;
end

%NOW TRY LOADING IN THE REFERENCE SCAN DATA (IF IT EXISTS)
isRef=false;
if exist([inDir '/fid.ref'])
    isRef=true;
    ref_data=fread(fopen([inDir '/fid.ref']),'int');
    real_ref = ref_data(2:2:length(ref_data));
    imag_ref = ref_data(1:2:length(ref_data));
    fids_ref=real_ref-1i*imag_ref;

    fids_ref=reshape(fids_ref,[],rawAverages);
    fids_ref_trunc=fids_ref(ADC_OFFSET:end,:);
    %         fids_trunc=fids_trunc';
    reffids=padarray(fids_ref_trunc, [ADC_OFFSET-1,0],'post');
    refspecs=fftshift(ifft(reffids,[],1),1);
    sz=size(refspecs);
    out.flags.averaged=0;
    %specify the dims
    refdims.t=1;
    refdims.coils=0;
    refdims.averages=2;
    refdims.subSpecs=0;
    refdims.extras=0;
end

%%%%%Chathu mod ends

%Now get some of the relevent spectral parameters

%First get the spectral width
method_fid=fopen([inDir '/method']);
line=fgets(method_fid);
index=findstr(line,'$PVM_DigSw=');
while isempty(index)
    line=fgets(method_fid);
    index=findstr(line,'$PVM_DigSw=');
end
equals_index=findstr(line,'=');
spectralwidth=line(equals_index+1:end);
spectralwidth=str2double(spectralwidth);
fclose(method_fid);

%Now get the transmitter frequency
acqp_fid=fopen([inDir '/acqp']);
line=fgets(acqp_fid);
index=findstr(line,'$BF1=');
while isempty(index)
    line=fgets(acqp_fid);
    index=findstr(line,'$BF1=');
end
equals_index=findstr(line,'=');
txfrq=line(equals_index+1:end);
txfrq=str2double(txfrq);
txfrq=txfrq*1e6;
fclose(acqp_fid);

%B0
Bo=txfrq/42577000;

%Spectral width in PPM
spectralwidthppm=spectralwidth/(txfrq/1e6);

%Now get the TE
method_fid=fopen([inDir '/method']);
line=fgets(method_fid);
index=findstr(line,'$PVM_EchoTime=');
%%%%%CHATHU MOD for FIDS with Pulse acquire
loop_count=0;
TE_present=true;
while isempty(index) && TE_present
    line=fgets(method_fid);
    index=findstr(line,'$PVM_EchoTime=');
    loop_count=loop_count+1;
    if loop_count>10000
        TE_present=false;
    end
end

if TE_present
    equals_index=findstr(line,'=');
    te=line(equals_index+1:end);
    te=str2double(te);
else
    te=0;
end

%%%%%CHATHU MOD for FIDS with Pulse acquire END
fclose(method_fid);

%Now get the TR
method_fid=fopen([inDir '/method']);
line=fgets(method_fid);
index=findstr(line,'$PVM_RepetitionTime=');
while isempty(index)
    line=fgets(method_fid);
    index=findstr(line,'$PVM_RepetitionTime=');
end
equals_index=findstr(line,'=');
tr=line(equals_index+1:end);
tr=str2double(tr);
fclose(method_fid);

%Now get the sequence
method_fid=fopen([inDir '/method']);
line=fgets(method_fid);
index=findstr(line,'$Method=');
while isempty(index)
    line=fgets(method_fid);
    index=findstr(line,'$Method=');
end
equals_index=findstr(line,'=');
sequence=line(equals_index+1:end);
sequence=strtrim(sequence);
fclose(method_fid);

%Specify the number of subspecs.  For now, this will always be one.
subspecs=1;
rawSubspecs=1;

%calculate the ppm scale
ppm=[4.65+(spectralwidthppm/2):-spectralwidthppm/(length(specs)-1):4.65-(spectralwidthppm/2)];

%calculate the dwelltime:
dwelltime=1/spectralwidth;

%calculate the time scale
t=[0:dwelltime:(sz(1)-1)*dwelltime];

%FILLING IN DATA STRUCTURE FOR THE FID.RAW DATA
out.fids=fids;
out.specs=specs;
out.sz=sz;
out.ppm=ppm;
out.t=t;
out.spectralwidth=spectralwidth;
out.dwelltime=dwelltime;
out.txfrq=txfrq;
out.date=date;
out.dims=dims;
out.Bo=Bo;
out.averages=rawAverages;
out.rawAverages=rawAverages;
out.subspecs=subspecs;
out.rawSubspecs=rawSubspecs;
out.seq=sequence;
out.te=te;
out.tr=tr;
out.pointsToLeftshift=0;

%FILLING IN THE FLAGS FOR THE FID.RAW DATA
out.flags.writtentostruct=1;
out.flags.gotparams=1;
out.flags.leftshifted=0;
out.flags.filtered=0;
out.flags.zeropadded=0;
out.flags.freqcorrected=0;
out.flags.phasecorrected=0;

out.flags.addedrcvrs=1;
out.flags.subtracted=0;
out.flags.writtentotext=0;
out.flags.downsampled=0;
out.flags.avgNormalized=0;
if out.dims.subSpecs==0
    out.flags.isFourSteps=0;
else
    out.flags.isFourSteps=(out.sz(out.dims.subSpecs)==4);
end

if isRef
    %FILLING IN DATA STRUCTURE FOR THE FID.REF DATA
    ref.fids=reffids;
    ref.specs=refspecs;
    ref.sz=sz;
    ref.ppm=ppm;
    ref.t=t;
    ref.spectralwidth=spectralwidth;
    ref.dwelltime=dwelltime;
    ref.txfrq=txfrq;
    ref.date=date;
    ref.dims=dims;
    ref.Bo=Bo;
    ref.averages=rawAverages;
    ref.rawAverages=rawAverages;
    ref.subspecs=subspecs;
    ref.rawSubspecs=rawSubspecs;
    ref.seq=sequence;
    ref.te=te;
    ref.tr=tr;
    ref.pointsToLeftshift=0;

    %FILLING IN THE FLAGS FOR THE FID.REF DATA
    ref.flags.writtentostruct=1;
    ref.flags.gotparams=1;
    ref.flags.leftshifted=0;
    ref.flags.filtered=0;
    ref.flags.zeropadded=0;
    ref.flags.freqcorrected=0;
    ref.flags.phasecorrected=0;

    ref.flags.addedrcvrs=1;
    ref.flags.subtracted=0;
    ref.flags.writtentotext=0;
    ref.flags.downsampled=0;
    ref.flags.avgNormalized=0;
    if ref.dims.subSpecs==0
        ref.flags.isFourSteps=0;
    else
        ref.flags.isFourSteps=(ref.sz(ref.dims.subSpecs)==4);
    end
end


function I = gif2RGB(gifFile)
[x, map] = imread(gifFile);
I = ind2rgb(x, map);


function varargout  =   vect2var(varargin)
%VECT2VAR Unpack vector to variables
%
%     [x1, x2, x3,...] =   vect2var(X) create variables x1, x2, x3... from
%     the vector X in the current workspace such as x1 = X(1), x2 = X(2),
%     x3 = X(3)...
%     vect2var is usefull with the optimization toolbox in which unknown
%     variables can be grouped into a single row vector. vect2var allows
%     the use of common names for variables with a minimum waste of time.
%
%     Example :
%     X     =   [3E5    20   5   0.898];
%     [b f jh ws] =   vect2var(X)
%     Returns :
%       b =
%             300000
%       f =
%           20
%       jh =
%            5
%       ws =
%           0.8980
%
%     See also DEAL, MMV2STRUCT, LISTS

%   vect2var is complementary of mmv2struct developped by D.C. Hanselman
%   Author : Meille Christophe
%   Pharmacokinetics Department, UFR Pharmacy, Marseille France
%   Version 1.07    Date: 2005/11/18

X   =   varargin{1};% Extract vector X
lgt =   nargout;    % Extract number of outputs
if ndims(X)>2       % Error handling
    error('Input vector required.')
elseif length(X)<lgt
    error('Input vector shorter than number of outputs.')
else
    varargout = cell(1,lgt);% preallocating cell array
    for i=1:lgt;% index of outputs
        varargout{i}    =   X(i); % unpack
    end
end


function [S, mets, badRxns, reversible]=constructS(equations,mets,rxns)
% constructS
%   Constructs a stoichiometric matrix from a cell array of equations
%
%   equations   cell array of equations on the form 'A + 2 B <=> 3 C',
%               where <=> indicates reversible and => irreversible reactions
%   mets        cell array of metabolites. All metabolites in the equations
%               must be present in the list (opt, default generated from
%               the equations)
%   rxns        cell array of reaction ids. This is only used for printing
%               reaction ids instead of equations in warnings/errors (opt,
%               default [])
%
%   S           the resulting stoichiometric matrix mets cell array with
%               metabolites that corresponds to the order in the S matrix
%   badRxns     boolean vector with the reactions that have one or more
%               metabolites as both substrate and product. An example would
%               be the phosphotransferase ATP + ADP <=> ADP + ATP. In the
%               stoichiometric matrix this equals to an empty reaction
%               which can be problematic
%   reversible  boolean vector with true if the equation is reversible
%
%   Usage: [S, mets, badRxns, reversible]=constructS(equations,mets)

equations=convertCharArray(equations);
switch nargin
    case 2
        mets=convertCharArray(mets);
    case 3
        rxns=convertCharArray(rxns);
end

badRxns=false(numel(equations),1);

%Check that no equations are too short to have reversibility data
I=cellfun(@numel,equations);
I=find(I<4,1);
if any(I)
    if isempty(rxns)
        EM=['The following equation does not have reversibility data: ' equations{I} ];
        dispEM(EM);
    else
        EM=['The reaction ' rxns{I} ' does not have reversibility data'];
        dispEM(EM);
    end
end

%Makes life a little easier
equations=strtrim(equations);
equations=fixEquations(equations);

if nargin<2
    mets=parseRxnEqu(equations);
end
if nargin<3
    rxns=[];
end

%Get which reactions are reversible
reversible=cellfun(@any,strfind(equations,' <=> '));

%Make them all reversible. This is not all that neat, but nevermind
equations=strrep(equations,' => ',' <=> ');

%Replace the the plus signs with some weird character that will be used for
%parsing
equations=strrep(equations,' + ', '€');

%Generate the stoichiometric matrix
S=zeros(numel(mets),numel(equations));

%Keep track of coefficients to be added to S-matrix
metsToS = cell(100000,1);
rxnsToS = zeros(100000,1);
coefToS = zeros(100000,1);
newEntry = 1;
%Loop through the equations and add the info to the S matrix
for i=1:numel(equations)
    %Start by finding the position of the (=> or <=>)
    arrowIndex=strfind(equations{i},' <=> ');

    if numel(arrowIndex)~=1
        if isempty(rxns)
            EM=['The following equation does not have reversibility data: ' equations{i} ];
            dispEM(EM);
        else
            EM=['The reaction ' rxns{i} ' does not have reversibility data'];
            dispEM(EM);
        end
    end

    reactants=regexp(equations{i}(1:arrowIndex-1),'€','split');
    products=regexp(equations{i}(arrowIndex+5:end),'€','split');

    %If the splitting character is at the end (if exchange rxns), then an
    %empty string will exist together with the real ones. Remove it
    reactants(cellfun(@isempty,reactants))=[];
    products(cellfun(@isempty,products))=[];

    %A vector where an element is -1 is the corresponding metabolite is a
    %reactant and 1 if it's a product
    multiplyWith=[ones(numel(reactants),1)*-1; ones(numel(products),1)];

    metabolites=strtrim([reactants products]);

    %Now loop through the reactants and see if the metabolite has a
    %coefficient (it will look as 'number name')
    for j=1:numel(metabolites)
        space=strfind(metabolites{j},' ');

        if isempty(space)
            %No coefficient
            coeff=1;
            name=metabolites{j};
        else
            coeff=str2double(metabolites{j}(1:space(1)));

            %If it was not a coefficiant
            if isnan(coeff)
                coeff=1;
                name=strtrim(metabolites{j});
            else
                name=strtrim(metabolites{j}(space+1:end));
            end
        end

        %Find the name in the mets list [a b]=ismember(name,mets);
        metsToS{newEntry}=name;
        rxnsToS(newEntry)=i;
        coefToS(newEntry)=coeff*multiplyWith(j);
        newEntry=newEntry+1;
    end
end
%Remove unused fields
metsToS(newEntry:end)=[];
rxnsToS(newEntry:end)=[];
coefToS(newEntry:end)=[];

%Match to mets array
[metsPresent,metsLoc]=ismember(metsToS,mets);

%Find badRxns
[~,I]=unique([rxnsToS,metsLoc],'rows','stable');
x=1:length(rxnsToS);
x(I)=[];
x=unique(rxnsToS(x));
badRxns(x)=true;

if any(~metsPresent)
    if isempty(rxns)
        error(['Could not find the following metabolites in the metabolite list: ',...
        strjoin(unique(metsToS(~metsPresent)),', ')],'')
    else
        missingMet = find(~metsPresent);
        missingMet = char(strcat(metsToS(missingMet),' (reaction:',rxns(rxnsToS(missingMet)),')\n'));
        error(['Could not find the following metabolites (reaction indicated) in the metabolite list: \n' ...
            missingMet '%s'],'');
    end
end
linearIndices=sub2ind(size(S),metsLoc,rxnsToS);
S(linearIndices)=coefToS;
S=sparse(S);
end

function equ=fixEquations(equ)
%If the equation starts with "=>" or "<=>" then add a space again. This is
%an alternative way to represent uptake reactions. The opposite way for
%producing reactions
equ=equ(:);
for i=1:numel(equ)
    if strcmp(equ{i}(1:2),'=>') || strcmp(equ{i}(1:3),'<=>')
        equ{i}=[' ' equ{i}];
    else
        if strcmp(equ{i}(end-1:end),'=>') || strcmp(equ{i}(end-2:end),'<=>')
            equ{i}=[equ{i} ' '];
        end
    end
end
end


% Script demo_model_estimation_1st_level
% 1st level model specification and estimation
%
%  demo_model_estimation_1st_level
%
%
%   See also

% Author:   Saskia Bollmann & Lars Kasper
% Created:  2018-05-04
% Copyright (C) 2018 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 License (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/>.

clear;
close all;
clc;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% (0) User Inputs
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% uses the output of demo_preprocessing; PLEASE MODIFY TO YOUR PATH
pathOutputDemoPreprocessing = fullfile(pwd, 'preprocessing', 'MrSeries_*');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% (1) Load data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

S = MrSeries(pathOutputDemoPreprocessing);
% change directory to get a separate it from the preprocessing
S.parameters.save.path = strrep(S.parameters.save.path, 'preprocessing', 'model_estimation');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% (2) Make brain mask
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% add white and grey matter TPMs
S.additionalImages{end+1} = S.tissueProbabilityMaps{1} + S.tissueProbabilityMaps{2};
S.additionalImages{4}.name = 'brain_tpm';
S.additionalImages{4}.parameters.save.fileName = 'brain_tpm.nii';
S.additionalImages{4}.plot;
% set parameters for mask
S.parameters.compute_masks.nameInputImages = 'brain_tpm';
S.parameters.compute_masks.nameTargetGeometry = 'mean';
S.compute_masks;
% check mask
S.mean.plot('overlayImages', S.masks{2});
% close mask
S.masks{3} = S.masks{2}.imclose(strel('disk', 5));
% check again
S.mean.plot('overlayImages', S.masks{3});
% perfect - save new mask
S.masks{3}.save;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% (3) Specify Model
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% timing in seconds
S.glm.timingUnits = 'secs';
% repetition time - check!
disp(['The specified TR is ', num2str(S.data.geometry.TR_s), 's.']);
S.glm.repetitionTime = S.data.geometry.TR_s;
% model derivatives
S.glm.hrfDerivatives = [1 1];

% add conditions
% specify block length
block_length = 20;
% specify condition onset
condition = 20:40:380;
% remove 5 first TRs
condition_onsets = condition - 5 * S.data.geometry.TR_s;

% add to glm
S.glm.conditions.names = {'tapping'};
S.glm.conditions.onsets = {condition_onsets};
% add durations
S.glm.conditions.durations = {block_length};
% add an explicit mask
S.glm.explicitMasking = S.masks{3}.get_filename;
% turn of inplicit masking threshold;
S.glm.maskingThreshold = -Inf;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% (4) Estimate Model
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% compute stat images
S.compute_stat_images;
% estimate
S.specify_and_estimate_1st_level;
% look at design matrix
S.glm.plot_design_matrix;


function [C,group_sizes]=contour_group(varargin)

%function [C,group_sizes]=contour_group(X,Y,Z,M,Sx,Sy,Sz,c,interpMethod)

%% Parse input

switch nargin
    case 8
        X=varargin{1};
        Y=varargin{2};
        Z=varargin{3};
        M=varargin{4};
        Sx=varargin{5};
        Sy=varargin{6};
        Sz=varargin{7};
        c=varargin{8};
        interpMethod='linear';
    case 9
        X=varargin{1};
        Y=varargin{2};
        Z=varargin{3};
        M=varargin{4};
        Sx=varargin{5};
        Sy=varargin{6};
        Sz=varargin{7};
        c=varargin{8};
        interpMethod=varargin{9};
end
%% Create contours
% Open figure window with visibility off

ht=figure('Visible','off');
if ndims(M)==3

else %2D array
    X(:,:,2)=X; Y(:,:,2)=Y; Z(:,:,2)=Z+1; M(:,:,2)=M;
end

%Contourslice is used since it provides children in handles
h=contourslice(X,Y,Z,M,Sx,Sy,Sz,[c c],interpMethod); %This will plot in invisible window

%% Parse children
%

C=cell(1,numel(h));
for i=1:length(h)
    %Get coordinates
    x=get(h(i),'XData'); y=get(h(i),'YData'); z=get(h(i),'ZData');

    %Vertices matrix
    V=[x(:) y(:) z(:)];
    V=V(all(~isnan(V),2),:); %Removing NaN's

    %Store in cell array
    C{i}=V;
end

%Get group sizes
group_sizes = cell2mat(cellfun(@(x) size(x,1), C,'UniformOutput',0)');

%Remove contours of lenght 1
C=C(group_sizes>1);
group_sizes=group_sizes(group_sizes>1);

%Sort C array according to group size
[group_sizes,ind_sort]=sort(group_sizes);
C=C(ind_sort);

close(ht);

end

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


 function h = im(varargin)
%function h = im([options,] [xx,] [yy,] zz, [scale|clim,] [title])
%| show matrix zz as an image, possibly with (x,y) axes labeled by xx,yy
%|
%| options:
%|	subplot		an integer for subplot
%|	'notick'	no axis tick marks
%|	'black0'	make sure image value of 0 is black (max white)
%|	'blue0'		show zeros as blue
%|	'mid3'		show middle 3 planes of 3D volume
%|	'mip3'		show 3 MIP (max. intens. proj.) views of 3D volume
%|	'row', n	# of rows for 3D montages, for this call
%|	'col', n	# of cols for 3D montages, for this call
%|
%| after options:
%|	scale		scale image by this factor
%|	clim		limits for colorbar
%|	title		axis title, processed by titlef()
%|	'cbar'		add colorbar
%|
%| one argument commands:
%|	'off'		disable display,
%|	'off-quiet'	disable display, and do not print 'disabled' messages
%|	'on'		enable display, 'ison' report if enabled
%|	'clf'		clear display (if enabled)
%|	'colorneg'	show negatives as red
%|	'db40'		log grayscale over 40dB range
%|	'nan-warn'	warning if nan value(s), 'nan-fail' fail if nan
%|	'drawnow'	'drawnot' toggle immediate drawing
%|	'tickon'	'tickoff' toggle default tick drawing
%|	'tick1'		axis ticks [1 N] (default)
%|	'tick0'		axis ticks [0 N-1]
%|	'state'		report state
%|
%| other commands:
%|	'pl' sub_m sub_n specify subplot layout for subsequent plots
%|	'plc'		like 'pl' but first clf
%|	'pl-tight'	like 'pl' but tight plots with little (if any) spacing
%|	'subplot' plotindex	choose a subplot
%|	n2min	n		<= this min # for dim2 we plot instead (def: 1)
%|	zero blue	replace 1st colormap entry (zero?) with blue
%|	row n		# of rows for 3D montages - setting state
%|	col n		# of cols for 3D montages - setting state
%|
%| Copyright 1997, Jeff Fessler, University of Michigan

% handle states
persistent state
if ~isvar('state') || isempty(state)
	state = ir_im_reset;
end

% default is to give help
if ~nargin && ~nargout
	help(mfilename)
	if im, printm('im enabled'), else, printm('im disabled'), end
	fail(mfilename)
end

% for conditional of the form 'if im, ..., end'
if ~nargin && nargout
	h = state.display;
return
end

% im row 2 or im col 3
if nargin == 2 && (streq(varargin{1}, 'row') || streq(varargin{1}, 'col'))
	tmp = varargin{2};
	if ischar(tmp), tmp = str2num(tmp); end
	state.montage = {varargin{1}, tmp};
return
end

% process single string command arguments
if nargin == 1 && ischar(varargin{1})
	arg = varargin{1};

	switch arg
	case 'on'
		state.display = true;
		state.display_quiet = false;
		disp 'enabling images'
	case 'off'
		state.display = false;
		state.display_quiet = false;
		disp 'disabling images'
	case 'off-quiet'
		state.display = false;
		state.display_quiet = true;
	case 'clf'
		if state.display
			state.sub_m = [];
			clf
		end
	case 'drawnow'
		state.drawnow = true;
	case 'drawnot'
		state.drawnow = false;
	case 'subplot'
		if state.sub_m
			im_subplot(state, state.next_sub);
			state.next_sub = state.next_sub + 1;
		else
			fail('subplot not set')
		end
	case 'tickon'
		state.tick = true;
	case 'tickoff'
		state.tick = false;
	case 'tick1'
		state.ticks = 'tick1'; % [1 N]
	case 'tick0'
		state.ticks = 'tick0'; % [0 N-1]
	case 'tickc'
		state.ticks = 'tickc'; % [-(N-1)/2 0 (N-1)/2]
	case 'ison' % query
		if state.display
			h = true;
		else
			h = false;
		end
	case 'state' % query
		h = state;
	case 'nan-fail'
		state.nan_fail = true;
	case 'nan-warn'
		state.nan_fail = false;
	case 'blue0'
		state.blue0 = true;
	case 'colormap_keep'
		state.colormap_control = '';
	case 'colorneg'
		state.colorneg = true;
	case 'reset'
		state = ir_im_reset;
	case 'test'
		im_test, return
	otherwise
		if streq(arg, 'db', 2)
			state.db = sscanf(arg, 'db%g');
		else
			fail('unknown argument: "%s"', arg)
		end
	end
return
end

% 'pl' 'plc' 'pl-tight' option
if streq(varargin{1}, 'pl') || streq(varargin{1}, 'pl-tight') ...
	|| streq(varargin{1}, 'plc')
	if streq(varargin{1}, 'plc'), im clf, end
	if nargin == 3
		state.sub_m = ir_ensure_num(varargin{2});
		state.sub_n = ir_ensure_num(varargin{3});
	elseif nargin == 1
		state.sub_m = [];
		state.sub_n = [];
	else
		fail 'bad pl usage'
	end
	state.pl_tight = streq(varargin{1}, 'pl-tight');
	state.next_sub = 1;
return
end

% 'subplot' option
if streq(varargin{1}, 'subplot')
	state = im_subplot(state, ir_ensure_num(varargin{2}));
return
end

% 'n2min' option
if streq(varargin{1}, 'n2min')
	state.n2min = ir_ensure_num(varargin{2});
return
end

% 'zero' or 'zero blue'
if streq(varargin{1}, 'zero')
	cmap = get(gcf, 'colormap');
	cmap(1,:) = [0 0 1];
	set(gcf, 'colormap', cmap);
return
end

scale = 1;
titlearg = {};
opt.cbar = false;
clim = [];
xx = [];
yy = [];
opt.blue0 = false; % 1 to color 0 as blue
opt.colorneg = false; % 1 to put negatives in color and 0=blue
opt.db = 0; % nonzero to use a log scale
isxy = false; % 1 if user provides x and y coordinates
isplot = false;
opt.tick = state.tick;
opt.ticks = state.ticks;
opt.black0 = false;
opt.mid3 = false; % 1 if show mid-plane slices of 3D object
opt.mip3 = false; % 1 if show 3 MIP views of 3D object
opt.montage = state.montage;
opt.hsv = false;

if length(varargin) == 1 && isempty(varargin{1})
	fail 'empty argument?'
end

% optional arguments
zz_arg_index = 1;
while length(varargin)
	arg = varargin{1};
	if isempty(arg)
		0; % do nothing
	elseif max(size(arg)) == 1 % scalar
		if state.display
			arg1 = varargin{1};
			if arg1 > 99 % reset
				state.sub_m = [];
				state.sub_n = [];
			end
			if isempty(state.sub_m)
				if arg1 >= 111
					subplot(arg1)
				else
					printm('ignoring subplot %d', arg1)
				end
			else
				state = im_subplot(state, arg1);
			end
		end
	elseif streq(arg, 'notick')
		opt.tick = false;
	elseif streq(arg, 'tick1')
		opt.ticks = 'tick1'; % [1 N]
	elseif streq(arg, 'tick0')
		opt.ticks = 'tick0'; % [0 N-1]
	elseif streq(arg, 'tickc')
		opt.ticks = 'tickc'; % [-(N-1)/2 0 (N-1)/2]
	elseif streq(arg, 'colorneg')
		opt.colorneg = true;
	elseif streq(arg, 'db', 2)
		opt.db = sscanf(arg, 'db%g');
	elseif streq(arg, 'black0')
		opt.black0 = true;
	elseif streq(arg, 'blue0')
		opt.blue0 = true;
	elseif streq(arg, 'hsv')
		opt.hsv = true;
	elseif streq(arg, 'mid3')
		opt.mid3 = true;
	elseif streq(arg, 'mip3')
		opt.mip3 = true;
	elseif streq(arg, 'row') || streq(arg, 'col')
		opt.montage = {arg, varargin{2}};
		varargin = {varargin{2:end}};
		zz_arg_index = 1 + zz_arg_index;
	else
		break
	end

	varargin = {varargin{2:end}};
	zz_arg_index = 1 + zz_arg_index;
end

if length(varargin) < 1, ir_usage, end

if ~isempty(state.sub_m) % possibly redundant but ok
	nplot = state.sub_m * state.sub_n;
	im_subplot(state, 1 + mod(state.next_sub-1, nplot));
	state.next_sub = state.next_sub + 1;
end

% plotting vector(s)
if ndims(varargin{1}) <= 2 && min(size(varargin{1})) <= state.n2min ...
	&& length(varargin) < 3
		isplot = true;
		plot_data = varargin{1};

% xx, yy
elseif ndims(varargin{1}) <= 2 && min(size(varargin{1})) == 1
	xx = col(varargin{1});
	if length(varargin) < 2, help(mfilename), fail 'need both xx,yy', end
	if min(size(varargin{2})) ~= 1, fail 'both xx,yy need to be 1D', end
	yy = col(varargin{2});
	varargin = {varargin{3:end}};
	isxy = 1;
	zz_arg_index = 2 + zz_arg_index;
end

if ~state.display
	if ~state.display_quiet
		printm(['disabled: ' inputname(zz_arg_index)])
	end
return
end

% zz
if length(varargin)
	zz = varargin{1};
	if iscell(zz); zz = stackup(zz{:}); isplot = 0; end % trick
	zz = double(zz);
	if ndims(zz) > 2 && min(size(zz)) == 1
		zz = squeeze(zz); % handle [1 n2 n3] case as [n2 n3]
	end
	varargin = {varargin{2:end}};
else
	fail 'no image?'
end

if any(isnan(zz(:)))
	tmp = sprintf('image contains %d NaN values of %d!?', ...
		sum(isnan(zz(:))), numel(zz));
	if state.nan_fail, fail(tmp), else, warning(tmp), end
end

if any(isinf(zz(:)))
	tmp = sprintf('image contains %d Inf values of %d!?', ...
		sum(isinf(zz(:))), numel(zz));
	if state.nan_fail, fail(tmp), else, warning(tmp), end
end

if opt.mid3
	mip3_size = size(zz);
	pn = jf_protected_names;
	zz = pn.mid3(zz);
end

if opt.mip3
	mip3_size = size(zz);
	zz = jf_mip3(zz);
end

% title, scale, clim, cbar
while length(varargin)
	arg = varargin{1};
	if isempty(arg)
		% do nothing
	elseif ischar(arg)
		if streq(arg, 'cbar')
			opt.cbar = true;
		else
			titlearg = {arg};
		end
	elseif isnumeric(arg) % isa(arg, 'double')
		if max(size(arg)) == 1
			scale = arg;
		elseif all(size(arg) == [1 2])
			clim = arg;
		else
			fail 'nonscalar scale / nonpair clim?'
		end
%		pr scale
	else
		fail 'unknown arg'
	end
	varargin = {varargin{2:end}};
end

if isplot
	plot(plot_data, state.line1type)
	if ~isempty(titlearg), titlef(titlearg{:}), end
return
end

if issparse(zz), zz = full(zz); end
if ~isreal(zz)
	zz = abs(zz);
	printf('warn %s: magnitude of complex image', mfilename)
end

if opt.db || state.db
	if ~opt.db && state.db, opt.db = state.db, end
	if max(zz(:)) <= 0, fail 'db for negatives?', end
	zz = abs(zz); zz = max(zz, eps);
	zz = 10*log10(abs(zz) / max(abs(zz(:))));
	zz(zz < -opt.db) = -opt.db;
end

zmax = max(zz(:));
zmin = min(zz(:));

if opt.black0
	if ~isempty(clim)
		warning 'black0 overrules clim'
	end
	clim = [0 zmax];
end

if scale ~= 1
	if scale == 0
		zmin = 0;
		scale = 1;
	elseif scale < 0
		zmin = 0;
		scale = -scale;
	end
end

%% determine colormap and adjust data zz if necessary
function [zz, cmap] = im_cmap(zz, opt, state)
	cmap = [];
	if opt.blue0 || state.blue0
		cmap = [[0 0 1]; gray(256)];
%		colormap_gca(cmap)
%		colormap_cmap = cmap;
		zt = zz;
		zz(zt > 0) = 1+floor(255 * zz(zt > 0) / (abs(max(zt(:))) + eps));
		zz(zt == 0) = 1;

	elseif (opt.colorneg || state.colorneg) && ~ir_is_octave
		if 1 % original
			cmap = hot(512);	cmap = flipud(cmap(1:256,:));
			cmap = [cmap; [0 0 1]; gray(256)];
		else % +green -red
			tmp = [0:255]'/255;
			cmap = [flipud(tmp)*[1 0 0]; [0 0 1]; tmp*[0 1 0]];
		end
	%	colormap_gca(cmap)
	%	colormap_cmap = cmap;
		zt = zz;
		zz(zt > 0) = 257+1+floor(255 * zz(zt > 0) / (abs(max(zt(:))) + eps));
		zz(zt == 0) = 257;
		zz(zt < 0) = 1+floor(-255 * zz(zt < 0) / (abs(min(zt(:))) + eps));

	elseif opt.hsv
	%	colormap_gca(hsv(256))
		cmap = hsv(256);

	else
		switch state.colormap_control
		case 'gray'
		%	colormap_gca(gray(256))
			cmap = gray(256);
		case ''
			% do nothing
		otherwise
			fail('unknown colormap_control "%s"', state.colormap_control)
		end
	end
end

[zz, colormap_cmap] = im_cmap(zz, opt, state);

if scale ~= 1 % fix: use clim?
	n = size(colormap,1);
	if zmax ~= zmin
		zz = (n - 1) * (zz - zmin) / (zmax - zmin); % [0,n-1]
	else
		if zmin == 0
			zz(:) = 0;
			clim = [0 1];
		else
			zz(:) = n - 1;
		end
	end
	zz = 1 + round(scale * zz);
	zz = min(zz,n);
	zz = max(zz,1);
elseif zmin == zmax
	if zmin == 0
		clim = [0 1];
	else
		zz(:) = 1;
		clim = [0 1];
	end
end

if ndims(zz) < 3 % 2d
	zz = zz'; % trick: transpose for consistency with C programs
	if ir_is_octave && state.octave_yflip
		zz = flipdim(zz, 1); % trick: note zz' above
	end
	if isxy
		if length(xx) ~= size(zz,2), fail 'xx size', end
		if length(yy) ~= size(zz,1), fail 'yy size', end
		hh = image(xx, yy, zz, 'CDataMapping', 'scaled');
		if opt.tick
			switch opt.ticks
			case 'tick0'
				setgca(	'xtick', xx([1 end]), ...
					'ytick', yy([1 end]), ...
					'fontsize', ir_fontsize('im_axes'));
			case 'tickc'
				setgca('xtick', xx([1 ceil((end+1)/2) end]), ...
				'ytick', yy([1 ceil((end+1)/2) end]), ...
				'fontsize', ir_fontsize('im_axes'));
			end
		end
	else
		n1 = size(zz,2);
		n2 = size(zz,1);
		switch opt.ticks
		case 'tick1'
			xx = 1:n1;
			yy = 1:n2;
			xtick = [1 n1];
			ytick = [1 n2];
		case 'tick0'
			xx = 0:(n1-1);
			yy = 0:(n2-1);
			xtick = [0 n1-1];
			ytick = [0 n2-1];
		case 'tickc' % [- 0 +]
			xtick = [-1 0 1] * (n1-1)/2;
			ytick = [-1 0 1] * (n2-1)/2;
			xx = (-(n1-1)/2):((n1-1)/2);
			yy = (-(n2-1)/2):((n2-1)/2);
		end
		hh = image(xx, yy, zz, 'CDataMapping', 'scaled');
%		hh = image(zz, 'CDataMapping', 'scaled');
%		setgca('CLimMode','auto')

		% unclutter axes by only showing end limits
%		setgca('xtick', [1 n1], 'ytick', [1 n2])

		if opt.tick
			setgca('xtick', [], 'ytick', ytick)
			if is_pre_v7
				text(1, 1.04*(n2+0.5), '1', ...
					'horizontalalign', 'left', ...
					'verticalalign', 'top')
				text(n1, 1.04*(n2+0.5), num2str(n1), ...
					'horizontalalign', 'right', ...
					'verticalalign', 'top')
			elseif opt.mip3 || opt.mid3
				tmp = [1 mip3_size(1)+[0 mip3_size(3)]];
				setgca('xtick', tmp)
				tmp = [1 mip3_size(2)+[0 mip3_size(3)]];
				setgca('ytick', tmp)
			else
				setgca('xtick', xtick)
			end
			tmp = {'fontsize', ir_fontsize('im_axes')};
			setgca(tmp{:})
		end
		% problem with this is it fails to register
		% space used for 'ylabel'
		% so i stick with manual xtick since that is what overlaps
		% with the colorbar
		if 0 && opt.tick
			text(-0.01*n1, n2, '1', ...
				'verticalalign', 'bottom', ...
				'horizontalalign', 'right')
			text(-0.01*n1, 1, num2str(n2), ...
				'verticalalign', 'top', ...
				'horizontalalign', 'right')
		end
	end

else % 3d
	n1 = size(zz,1);
	n2 = size(zz,2);
	if 0 % white border
		zz(:,end+1,:) = max(zz(:));
		zz(end+1,:,:) = max(zz(:));
	end
	if ir_is_octave && state.octave_yflip
		zz = flipdim(zz, 2);
	end
	dimz = size(zz);
	zz = montager(zz, opt.montage{:});

	if isxy
		xx3 = [0:size(zz,1)/dimz(1)-1]*(xx(2)-xx(1))*dimz(1);
		xx3 = col(outer_sum(xx, xx3));
		yy3 = [0:size(zz,2)/dimz(2)-1]*(yy(2)-yy(1))*dimz(2);
		yy3 = col(outer_sum(yy, yy3));
		hh = image(xx3, yy3, zz', 'CDataMapping', 'scaled');
		if opt.tick && n1 > 1 && n2 > 1 % unclutter
			setgca('xtick', [xx(1) xx(end)], 'ytick', ...
				sort([yy(1) yy(end)]))
		end
		axis xy
	else
		hh = image(zz', 'CDataMapping', 'scaled');
		if opt.tick && n1 > 1 && n2 > 1 % unclutter
			setgca('xtick', [1 n1], 'ytick', [1 n2])
		end

		if state.line3plot % lines around each sub image
			m1 = size(zz,1) / n1;
			m2 = size(zz,2) / n2;
			plot_box = @(ox,oy,arg) plot(ox+[0 1 1 0 0]*n1+0.5, ...
					oy+[0 0 1 1 0]*n2+0.5, state.line3type, arg{:});
			n3 = dimz(3);
			for ii=0:n3-1
				i1 = mod(ii, m1);
				i2 = floor(ii / m1);
				hold on
				plot_box(i1*n1, i2*n2, ...
					{'linewidth', state.line3width})
				hold off
			end
		end
	end
end

if ~isempty(colormap_cmap)
	colormap_gca(colormap_cmap)
end

if (zmax == zmin)
%	fprintf('Uniform image %g [', zmin)
%	fprintf(' %g', size(zz))
%	fprintf(' ]\n')
	texts(0.5, 0.5, sprintf('Uniform: %g', zmin), 'center', 'color', 'blue')
end

if (opt.colorneg || state.colorneg) && ~ir_is_octave
	set(hh, 'CDataMapping', 'direct')
else
	if ~isempty(clim),
		setgca('CLim', clim)
	elseif ~ishold
		setgca('CLimMode', 'auto')
	end
end

setgca('tickdir', 'out')
%setgca('tickdir', 'in')

if nargout > 0
	h = hh;
end

% axis type depends on whether user provides x,y coordinates
if isxy
	if length(xx) > 1 && length(yy) > 1 && ...
		abs(xx(2)-xx(1)) == abs(yy(2)-yy(1)) % square pixels
		axis image
	end
	axis xy
else
	axis image
	if ir_is_octave && ~isvar('dimz') % 2d
		axis([0.5 n1+0.5 0.5 n2+0.5])
	end
end

if ~isempty(titlearg)
	titlef(titlearg{:})
else % default title
	tmp = inputname(zz_arg_index);
	tmp = sprintf('%s range: [%.3g %.3g]', tmp, zmin, zmax);
	title(tmp, 'interpreter', 'none')
end

if ~opt.tick
	setgca('xtick', [], 'ytick', [])
end

if opt.cbar, cbar, end

if state.drawnow, drawnow, end

end % im()

% ir_im_reset()
% reset state to its defaults
function state = ir_im_reset
	state.display = true;
	state.display_quiet = false;
	state.colorneg = false;
	state.db = 0;
	state.blue0 = false;
	state.nan_fail = false;
	state.drawnow = false;
	state.tick = true;
	state.ticks = 'tick1'; % [1 N] ticks, or [0 N-1] if 'tick0'
	state.octave_yflip = true; % 3.8.2 octave seems to ignore 'axis ij' and ydir
	state.montage = {}; % for montager
	state.next_sub = 1; % next subplot index % todo
	state.sub_m = []; % for subplot
	state.sub_n = [];
	state.n2min = 1;
	state.pl_tight = false;
	state.line3plot = true;
	state.line3type = 'y-';
	state.line3width = 1;
	state.line1type = '-'; % for 1D plots
	state.colormap_control = 'gray'; % default is to set it to gray(256) each time
end

function x = ir_ensure_num(x)
	if ischar(x), x = str2num(x); end
end

function colormap_gca(cmap)
	if ir_is_octave || isfreemat
		colormap(cmap)
	else
		colormap(gca, cmap)
	end
end

function state = im_subplot(state, num)
	if state.display
		if state.pl_tight
			num = num - 1;
			x = 1 / state.sub_n;
			y = 1 / state.sub_m;
			ny = floor(num / state.sub_n);
			nx = num - ny * state.sub_n;
			ny = state.sub_m - ny - 1;
			subplot('position', [nx*x ny*y x y])
		else
			if num > state.sub_m * state.sub_n
				warn('num=%d > nsubplot=%d; resetting', ...
					num, state.sub_m * state.sub_n)
				num = 1;
			end
			subplot(state.sub_m, state.sub_n, num)
		end
		state.next_sub = num;
	end
end

function setgca(varargin)
	set(gca, varargin{:})
end

function im_test
	im clf, im(rand(6))
	im clf, im pl-tight 2 3
	im(1, rand(3))
	im(2, rand(3))
	im(5, ones(3))
	prompt
	im clf, im(rand(2^7,2^7-2,4))
end


classdef TestBitwiseXor
    %TestBitwiseXor

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

    methods (Static)
        function test_rgb_images
            img1 = cv.imread(TestBitwiseXor.im, 'ReduceScale',2);
            img2 = cv.cvtColor(img1, 'RGB2HSV');

            % rectangular mask
            [h,w,~] = size(img1);
            mask = false([h w]);
            mask(100:h-100,100:w-100) = true;

            out = cv.bitwise_xor(img1, img2);
            validateattributes(out, {class(img1)}, {'size',size(img1)});
            expected = my_bitwise_xor(img1, img2);
            assert(isequal(out, expected));

            out = cv.bitwise_xor(img1, img2, 'Mask',mask);
            validateattributes(out, {class(img1)}, {'size',size(img1)});
            expected = my_bitwise_xor(img1, img2, mask);
            assert(isequal(out, expected));

            out = cv.bitwise_xor(img1, img2, 'Mask',mask, 'Dest',img1);
            validateattributes(out, {class(img1)}, {'size',size(img1)});
            expected = my_bitwise_xor(img1, img2, mask, img1);
            assert(isequal(out, expected));
        end

        function test_float_images
            img1 = cv.imread(TestBitwiseXor.im, 'ReduceScale',2);
            img1 = single(img1) ./ 255;
            img2 = cv.cvtColor(img1, 'RGB2HSV');
            img2(:,:,1) = img2(:,:,1) ./ 360;

            % circular mask
            [h,w,~] = size(img1);
            [X,Y] = meshgrid(1:w,1:h);
            c = fix([w h]/2); r = 50;
            mask = ((X-c(1)).^2 + (Y-c(2)).^2) < r^2;

            out = cv.bitwise_xor(img1, img2);
            validateattributes(out, {class(img1)}, {'size',size(img1)});
            expected = my_bitwise_xor(img1, img2);
            assert(isequaln(out, expected));

            out = cv.bitwise_xor(img1, img2, 'Mask',mask);
            validateattributes(out, {class(img1)}, {'size',size(img1)});
            expected = my_bitwise_xor(img1, img2, mask);
            assert(isequaln(out, expected));

            out = cv.bitwise_xor(img1, img2, 'Mask',mask, 'Dest',img1);
            validateattributes(out, {class(img1)}, {'size',size(img1)});
            expected = my_bitwise_xor(img1, img2, mask, img1);
            assert(isequaln(out, expected));
        end

        function test_vectors
            A = uint8([240 255 85]);
            B = uint8([15 15 170]);
            mask = [true false true];

            % uint8([255 240 255])
            out = cv.bitwise_xor(A, B);
            validateattributes(out, {class(A)}, {'size',size(A)});
            expected = bitxor(A, B);
            assert(isequal(out, expected));

            % uint8([255 0 255])
            out = cv.bitwise_xor(A, B, 'Mask',mask);
            validateattributes(out, {class(A)}, {'size',size(A)});
            expected = bitxor(A, B);
            expected(~mask) = 0;
            assert(isequal(out, expected));

            % uint8([255 255 255])
            out = cv.bitwise_xor(A, B, 'Mask',mask, 'Dest',A);
            validateattributes(out, {class(A)}, {'size',size(A)});
            expected = bitxor(A, B);
            expected(~mask) = A(~mask);
            assert(isequal(out, expected));
        end

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

end

function out = my_bitwise_xor(src1, src2, mask, dst)
    %MY_BITWISE_XOR  Similar to cv.bitwise_xor using core MATLAB functions

    if nargin < 3, mask = true(size(src1,1), size(src1,2)); end
    if nargin < 4, dst = zeros(size(src1), class(src1)); end

    % calculate bitwise XOR
    if isinteger(src1)
        out = bitxor(src1, src2);
    elseif isfloat(src1)
        if isa(src1, 'double')
            klass = 'uint64';
        elseif isa(src1, 'single')
            klass = 'uint32';
        end
        out = bitxor(typecast(src1(:), klass), typecast(src2(:), klass));
        out = reshape(typecast(out, class(src1)), size(src1));
    end

    % apply masking
    for k=1:size(out,3)
        out_slice = out(:,:,k);
        dst_slice = dst(:,:,k);
        out_slice(~mask) = dst_slice(~mask);
        out(:,:,k) = out_slice;
    end
end


function kmlStruct = kml2struct(kmlFile)
% kmlStruct = kml2struct(kmlFile)
%
% Import a .kml file as a vector array of shapefile structs, with Geometry, Name,
% Description, Lon, Lat, and BoundaryBox fields.  Structs may contain a mix
% of points, lines, and polygons.
%
% .kml files with folder structure will not be presented as such, but will
% appear as a single vector array of structs.
%
%

[FID msg] = fopen(kmlFile,'rt');

if FID<0
    error(msg)
end

txt = fread(FID,'uint8=>char')';
fclose(FID);

expr = '<Placemark.+?>.+?</Placemark>';

objectStrings = regexp(txt,expr,'match');

Nos = length(objectStrings);

for ii = 1:Nos
    % Find Object Name Field
    bucket = regexp(objectStrings{ii},'<name.*?>.+?</name>','match');
    if isempty(bucket)
        name = 'undefined';
    else
        % Clip off flags
        name = regexprep(bucket{1},'<name.*?>\s*','');
        name = regexprep(name,'\s*</name>','');
    end

    % Find Object Description Field
    bucket = regexp(objectStrings{ii},'<description.*?>.+?</description>','match');
    if isempty(bucket)
        desc = '';
    else
        % Clip off flags
        desc = regexprep(bucket{1},'<description.*?>\s*','');
        desc = regexprep(desc,'\s*</description>','');
    end

    geom = 0;
    % Identify Object Type
    if ~isempty(regexp(objectStrings{ii},'<Point', 'once'))
        geom = 1;
    elseif ~isempty(regexp(objectStrings{ii},'<LineString', 'once'))
        geom = 2;
    elseif ~isempty(regexp(objectStrings{ii},'<Polygon', 'once'))
        geom = 3;
    end

    switch geom
        case 1
            geometry = 'Point';
        case 2
            geometry = 'Line';
        case 3
            geometry = 'Polygon';
        otherwise
            geometry = '';
    end

    % Find Coordinate Field
    bucket = regexp(objectStrings{ii},'<coordinates.*?>.+?</coordinates>','match');
    % Clip off flags
    coordStr = regexprep(bucket{1},'<coordinates.*?>(\s+)*','');
    coordStr = regexprep(coordStr,'(\s+)*</coordinates>','');
    % Split coordinate string by commas or white spaces, and convert string
    % to doubles
    coordMat = str2double(regexp(coordStr,'[,\s]+','split'));
    % Rearrange coordinates to form an x-by-3 matrix
    [m,n] = size(coordMat);
    coordMat = reshape(coordMat,3,m*n/3)';

    % define polygon in clockwise direction, and terminate
    [Lat, Lon] = poly2ccw(coordMat(:,2),coordMat(:,1));
    if geom==3
        Lon = [Lon;NaN];
        Lat = [Lat;NaN];
    end

    % Create structure
    kmlStruct(ii).Geometry = geometry;
    kmlStruct(ii).Name = name;
    kmlStruct(ii).Description = desc;
    kmlStruct(ii).Lon = Lon;
    kmlStruct(ii).Lat = Lat;
    kmlStruct(ii).BoundingBox = [[min(Lon) min(Lat);max(Lon) max(Lat)]];
end


function factors = kernFactors(kern, factorType)

% KERNFACTORS Extract factors associated with transformed
% optimisation space. "factorType" is one of 'atox', 'xtoa',
% or 'gradfact', as follows.
%
% 'atox': transform unrestricted input parameters to a suitably
% restricted output range.
%
% 'xtoa': transform restricted parameters back to the unrestricted
% space where e.g. gradient-based parameter optimization is done.
%
% 'gradfact': These factors are derivatives of the
% form dx/da, where "x" is the transformed parameter (for example
% a parameter that is restricted to be positive by a suitable
% transformation) and "a" is the untransformed parameter, which
% usually can freely take any real values.
%
% COPYRIGHT : unknown original copyright, possibly Neil Lawrence
%
% COPYRIGHT : Jaakko Peltonen, 2011

% KERN

factors.index = [];
factors.val = [];
if ~isempty(kern.transforms)
  fhandle = str2func([kern.type 'KernExtractParam']);
  params = fhandle(kern);

  % Process each transformation used with this kernel. Each
  % transformation may affect several parameters.
  for i = 1:length(kern.transforms)
    % Get the parameter indices involved in the i:th transformation
    index = kern.transforms(i).index;
    factors.index = [factors.index index];

    % Get the handle of the transformation function of the i:th transformation
    fhandle = str2func([kern.transforms(i).type 'Transform']);

    % If the transformation has been provided with specific
    % settings (such as a custom output range), use the settings,
    % otherwise transform without settings
    if isfield(kern.transforms(i),'transformsettings') && ~isempty(kern.transforms(i).transformsettings)
      factors.val = [factors.val  ...
		     fhandle(params(index), factorType, kern.transforms(i).transformsettings)];
    else
      factors.val = [factors.val  ...
		     fhandle(params(index), factorType)];
    end

  end
end


function allBb2d = crop2DBB(allBb2d,imh,imw)
        allBb2d_comp1 = allBb2d(:,[1,2]);
        allBb2d_comp1(allBb2d_comp1<1) =1;
        allBb2d_comp3 = allBb2d(:,1)+allBb2d(:,3);
        allBb2d_comp3(allBb2d_comp3>imw)=imw;
        allBb2d_comp4 = allBb2d(:,2)+allBb2d(:,4);
        allBb2d_comp4(allBb2d_comp4>imh)=imh;
        if size(allBb2d,2)>4
            allBb2d = [allBb2d_comp1,allBb2d_comp3,allBb2d_comp4,allBb2d(:,5:end)];
        else
            allBb2d = [allBb2d_comp1,allBb2d_comp3,allBb2d_comp4];
        end
        allBb2d(:,[3,4])= allBb2d(:,[3,4])-allBb2d(:,[1,2]);
        allBb2d(allBb2d(:,3)<0| allBb2d(:,4)<0,:)=[];
end


function [gIX,B] = SortGroupIXbyScore(H,gIX,numU,descend) %#ok<INUSD>
% for ranking functions % new gIX is sorted based on H, size(H)=[numU,1];
if exist('descend','var'),
    [B,I] = sort(H,'descend');
else
    [B,I] = sort(H);
end

if ~exist('numU','var'),
    numU = length(unique(gIX));
end

gIX_last = gIX;
for i = 1:numU,
    gIX(gIX_last==I(i)) = i;
end
end


function pts2 = grFaceToPolygon(varargin)
%GRFACETOPOLYGON Compute the polygon corresponding to a graph face.
%
%   PTS2 = grFaceToPolygon(NODES, EDGES, FACES, INDF)
%   PTS2 = grFaceToPolygon(NODES, FACES, INDF)
%   Where NODES, EDGES, and FACES are internal data of graph, and INDF is
%   the index of the face to extract. The result is the (ordered) set of
%   points composing the face.
%
%
%   PTS2 = grFaceToPolygon(GRAPH, INDF)
%   use structure representation for graph. The structure GRAPH must
%   contain data for fields 'nodes' and 'faces'.
%
%   If several indices face indices are specified, result is a cell array
%   of polygons.
%
%   The number of columns of PTS2 is the same as for NODES.
%

% ------
% Author: David Legland
% E-mail: david.legland@grignon.inra.fr
% Created: 2005-11-30
% Copyright 2005-2022 INRA - CEPIA Nantes - MIAJ (Jouy-en-Josas)

if length(varargin)==2
    % argument is a graph structure
    graph = varargin{1};
    nodes = graph.nodes;
    faces = graph.faces;
    indf  = varargin{2};

elseif length(varargin)==3
    % arguments are nodes, faces and indices
    nodes = varargin{1};
    faces = varargin{2};
    indf  = varargin{3};

elseif length(varargin)==4
    % arguments are nodes, edges, faces and indices, we forget edges
    nodes = varargin{1};
    faces = varargin{3};
    indf  = varargin{4};
end

if iscell(faces)
    % faces is a cell array
    if length(indf)==1
        face = faces{indf};
        pts2 = nodes(face, :);
    else
        pts2 = cell(length(indf), 1);
        for i=1:length(indf)
            face = faces{indf(i)};
            pts2{i} = nodes(face, :);
        end
    end
else
    % faces is an indices array: all faces have same number of vertices
    if length(indf)==1
        face = faces(indf, :);
        pts2 = nodes(face, :);
    else
        pts2 = cell(length(indf), 1);
        for i=1:length(indf)
            face = faces(indf(i), :);
            pts2{i} = nodes(face, :);
        end
    end
end


function sde_milstein_benchmark(tests,N,Tol)
%SDE_MILSTEIN_BENCHMARK  Performance tests for SDE_MILSTEIN solver function.
%   SDE_MILSTEIN_BENCHMARK will perform all tests. See code (type 'edit
%   SDE_MILSTEIN_BENCHMARK' in the command window) for test details or to add
%   additional tests. The SDETools Toolbox must be on the Matlab path or in the
%   same directory as this function.
%
%   SDE_MILSTEIN_BENCHMARK(TESTS) where TESTS = [N1 N2 ... NM] is a vector of
%   specific test numbers (indices, 1 ... N) to run. Tests can be listed in any
%   order and will be run in the order specified.
%
%   SDE_MILSTEIN_BENCHMARK(TESTS,N)
%   SDE_MILSTEIN_BENCHMARK(TESTS,N,TOL)
%
%   Not part of the the SDETools Toolbox; used only for development.
%
%   See also: SDE_MILSTEIN, SDEARGUMENTS, SDE_MILSTEIN_UNITTEST,
%       SDE_MILSTEIN_VALIDATE, SDE_EULER_BENCHMARK

%   Andrew D. Horchler, horchler @ gmail . com, Created 4-2-11
%   Revision: 1.2, 5-3-13

% Make sure toolbox on path, otherwise ensure we're in right location and add it
if ~isempty(strfind(path,'SDETools'))
    if exist('sde_milstein','file') ~= 2
        error('SDETools:sde_milstein_benchmark:FunctionNotFound',...
             ['The SDETools Toolbox is appears to be on the Matlab path, '...
              'but the SDE_MILSTEIN solver function cannot be found.']);
    end
else
    if exist('../SDETools','dir') ~= 7
        error('SDETools:sde_milstein_benchmark:ToolboxNotFound',...
             ['The SDETools Toolbox is not be on the Matlab path and the '...
              'root directory of the of the toolbox, SDETools, is not in '...
              'the same directory as the ''test'' directory.']);
    end
    addpath('../SDETools');
    Cleanup = onCleanup(@()rmpath('../SDETools'));  % Make sure path is reset
    if exist('sde_milstein','file') ~= 2
        error('SDETools:sde_milstein_benchmark:FunctionNotFoundAfterAdd',...
             ['The SDETools Toolbox was added to the Matlab path, but the '...
              'SDE_MILSTEIN solver function cannot be found.']);
    end
end

% Validate input argument if it exists
if nargin >= 1
    if isempty(tests) || ~isnumeric(tests) || ~all(isfinite(tests))
        error('SDETools:sde_milstein_benchmark:InvalidArg1',...
              'Invalid argument 1.');
    end
    if any(tests < 1)
        error('SDETools:sde_milstein_benchmark:NotAnIndex',...
              'Tests are numbered as indices, from 1 to N.');
    end
    tests = floor(tests);
    RunTests = true;
else
    RunTests = false;
end

if nargin >= 2
    if isempty(N) || ~isnumeric(N) || ~all(isfinite(N))
        error('SDETools:sde_milstein_benchmark:InvalidArg2',...
              'Invalid argument 2.');
    end
    N = floor(N);
else
    N = 1e3;
end

if nargin == 3
    if isempty(Tol) || length(Tol) ~= 1 || ~isnumeric(Tol) || ...
            ~all(isfinite(Tol)) || Tol <= 0
        error('SDETools:sde_milstein_benchmark:InvalidArg2',...
              'Invalid argument 2.');
    end
    Tol = floor(Tol);
else
    Tol = 1e-3;
end

M = 16;
fi = cell(M,1);
gi = cell(M,1);
tspani = cell(M,1);
y0i = cell(M,1);
optsi = cell(M,1);

% no FOR loop cases

% scalar ICs

i = 1;
fi{i} = 1;
gi{i} = 1;
tspani{i} = 0:0.001:1;
y0i{i} = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Scalar, constant drift and diffusion, variable step-size';

i = i+1;
fi{i} = 1;
gi{i} = 1;
tspani{i} = 0:0.5:500;
y0i{i} = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Scalar, constant drift and diffusion, fixed step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.001:1;
y0i{i} = 0;
optsi{i} = sdeset('ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Scalar, constant drift and diffusion functions, variable step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.5:500;
y0i{i} = 0;
optsi{i} = sdeset('ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Scalar, constant drift and diffusion functions, fixed step-size';

i = i+1;
fi{i} = 1;
gi{i} = 1;
tspani{i} = 0:0.001:1;
y0i{i} = 0;
optsi{i} = sdeset('Diagonal','no');
oneout{i} = false;
description{i} = 'Scalar, constant drift, constant non-diagonal diffusion, variable step-size';

i = i+1;
fi{i} = 1;
gi{i} = 1;
tspani{i} = 0:0.5:500;
y0i{i} = 0;
optsi{i} = sdeset('Diagonal','no');
oneout{i} = false;
description{i} = 'Scalar, constant drift, constant non-diagonal diffusion, fixed step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.001:1;
y0i{i} = 0;
optsi{i} = sdeset('Diagonal','no','ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Scalar, constant drift function, constant non-diagonal diffusion function, variable step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.5:500;
y0i{i} = 0;
optsi{i} = sdeset('Diagonal','no','ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Scalar, constant drift function, constant non-diagonal diffusion function, fixed step-size';

% vector ICs

i = i+1;
fi{i} = ones(1000,1);
gi{i} = ones(1000,1);
tspani{i} = 0:0.001:1;
y0i{i}(1,1000) = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Vector, constant drift and diffusion, variable step-size';

i = i+1;
fi{i} = ones(1000,1);
gi{i} = ones(1000,1);
tspani{i} = 0:0.5:500;
y0i{i}(1,1000) = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Vector, constant drift and diffusion, fixed step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.001:1;
y0i{i} = zeros(1,1000);
optsi{i} = sdeset('ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Vector, constant drift and diffusion functions, variable step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.5:500;
y0i{i}(1,1000) = 0;
optsi{i} = sdeset('ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Vector, constant drift and diffusion functions, fixed step-size';

i = i+1;
fi{i} = ones(1000,1);
gi{i} = 1;
tspani{i} = 0:0.001:1;
y0i{i}(1,1000) = 0;
optsi{i} = sdeset('Diagonal','no');
oneout{i} = false;
description{i} = 'Vector, constant drift, constant non-diagonal diffusion, variable step-size';

i = i+1;
fi{i} = ones(1000,1);
gi{i} = 1;
tspani{i} = 0:0.5:500;
y0i{i}(1,1000) = 0;
optsi{i} = sdeset('Diagonal','no');
oneout{i} = false;
description{i} = 'Vector, constant drift, constant non-diagonal diffusion, fixed step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x(1)+1;
tspani{i} = 0:0.001:1;
y0i{i}(1,1000) = 0;
optsi{i} = sdeset('Diagonal','no','ConstFFUN','yes','ConstGFUN','yes');
paramsi{i} = [];
oneout{i} = false;
description{i} = 'Vector, constant drift function, constant non-diagonal diffusion function, variable step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x(1)+1;
tspani{i} = 0:0.5:500;
y0i{i}(1,1000) = 0;
optsi{i} = sdeset('Diagonal','no','ConstFFUN','yes','ConstGFUN','yes');
oneout{i} = false;
description{i} = 'Vector, constant drift function, constant non-diagonal diffusion function, fixed step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.001:1;
y0i{i} = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Scalar, diagonal diffusion function, variable step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.5:500;
y0i{i} = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Scalar, diagonal diffusion function, fixed step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.001:1;
y0i{i} = 0;
optsi{i} = sdeset('SDEType','Ito');
oneout{i} = false;
description{i} = 'Scalar, Ito type, diagonal diffusion function, variable step-size';

i = i+1;
fi{i} = @(t,x)x+1;
gi{i} = @(t,x)x+1;
tspani{i} = 0:0.5:500;
y0i{i} = 0;
optsi{i} = sdeset('SDEType','Ito');
paramsi{i} = [];
oneout{i} = false;
description{i} = 'Scalar, Ito type, diagonal diffusion function, fixed step-size';

% Memory allocation
i = i+1;
fi{i} = ones(500000,1);
gi{i} = ones(500000,1);
tspani{i} = 0:0.5:5;
y0i{i}(1,500000) = 0;
optsi{i} = [];
oneout{i} = false;
description{i} = 'Memory allocation: vector, constant drift and diffusion, fixed step-size';

m = length(fi);
if RunTests
    ts = tests(tests<=m);
else
    ts = 1:m;
end

Stream = RandStream('mt19937ar','Seed',0);

sp = ' ';
t = zeros(1,N);
lts = length(ts);
mt(1,lts) = 0;
st(1,lts) = 0;
ost = ceil(log10((lts+1)));
for k=1:lts
    i = ts(k);

    % Get arguments
    f = fi{i};
    g = gi{i};
    tspan = tspani{i};
    y0 = y0i{i};
    opts = optsi{i};

    % Ensure that all tests start out with same random variates
    try
        RandStream.setGlobalStream(Stream);
    catch                                   	%#ok<CTCH>
        RandStream.setDefaultStream(Stream);	%#ok<SETRS>
    end

    % Warm up function before timing
    if oneout{i}
        if isempty(opts)
            y = sde_milstein(f,g,tspan,y0);     %#ok<*NASGU>
        else
            y = sde_milstein(f,g,tspan,y0,opts);
        end
    else
        if isempty(opts)
            [y,w] = sde_milstein(f,g,tspan,y0);	%#ok<*ASGLU>
        else
            [y,w] = sde_milstein(f,g,tspan,y0,opts);
        end
    end

    j = 0;
    while true  % Timing loop
        j = j+1;

        % Time an iteration
        if oneout{i}
            if isempty(opts)
                tic
                y = sde_milstein(f,g,tspan,y0);
                t(j) = toc;
            else
                tic
                y = sde_milstein(f,g,tspan,y0,opts);
                t(j) = toc;
            end
        else
            if isempty(opts)
                tic
                [y,w] = sde_milstein(f,g,tspan,y0);
                t(j) = toc;
            else
                tic
                [y,w] = sde_milstein(f,g,tspan,y0,opts);
                t(j) = toc;
            end
        end

        % Check if times are sufficient
        if N < 20 && N >= 10
            if (j >= 10 && sum(t(1:j)) > 0.1 && std(t(1:j)) < Tol) || j > N
                break
            end
        elseif N < 10
            if j > N
                break
            end
        else
            if (j >= 10 && sum(t(1:j)) > 0.1 && std(t(1:j)) < Tol) || ...
                    (j >= 20 && sum(t(1:j)) > 2) || j > N || sum(t(1:j)) > 5
                break
            end
        end
    end
    mt(k) = mean(t(1:j));
	st(k) = std(t(1:j));
    fprintf(1,[description{k} '\n']);
    fprintf(1,['Test %s%d took an average of %1.3e sec. (%1.3e '...
               'sec./time-step) over %d runs.\n\n'],...
              sp(ones(1,ost-ceil(log10((i+1))))),i,mt(k),mt(k)/length(tspan),j);
end
fprintf(1,'Total mean time for all %d tests: %4.4f +/- %4.4f sec.\n',...
	lts,sum(mt),mean(st));


function midi = extractPitch(configMfcc, configEsi, x, mfccHmm, esiHmm)
%EXTRACTPITCH   Function for A/U/V decision and pitch tracking.
%   Format: midi = extractPitch(configMfcc, configEsi, x, mfccHmm, esiHmm
%   Inputs:
%       configMfcc: Configuration for MFCC features.
%       configEsi:  Configuration for ESI features.
%       x:          Input signal.
%       mfccHmm:    HMM for MFCC features.
%       esiHmm:     HMM for ESI features.
%   Output:
%       midi:       Row vector containing the exxtracted pitch contour, in
%                   midi number scale, one number per frame. 0 stands for
%                   accompaniment, and -1 stands for unvoiced regions.

    mfcc = mfccFeature(configMfcc, x);
    sal = salience(configEsi, x);
    esi = esiFeature(configEsi, sal);

    midi = viterbi(mfcc, mfccHmm);
    segs = findSegs(midi == 3); % find voiced segs
    midi(midi == 1) = 0;        % accom
    midi(midi == 2) = -1;       % unvoiced
    for s = 1:size(segs,1)
        ind = segs(s,1) : segs(s,2);
        midi(ind) = refinePitch(configEsi, viterbi(esi(:,ind), esiHmm), sal(:,ind));
    end
end

function midi = refinePitch(config, state, sal)
% Refine pitch contour by picking the peaks in the salience map around the
%   coarse pitch contour.
    frames = length(state);
    midi = config.midisCoarse(state);
    for f = 1:frames
        ind = find((config.midisFine >= midi(f) - 0.5) & (config.midisFine <= midi(f) + 0.5));
        midis = config.midisFine(ind);
        [temp ind] = max(sal(ind, f));
        midi(f) = midis(ind);
    end
end

function segs = findSegs(bool)
% Find continuous segments of 1 in bool.
    bool = bool(:);
    start = bool & ~[0; bool(1:end-1)];
    finish = bool & ~[bool(2:end); 0];
    segs = [find(start), find(finish)];
end