function model = yalmip2nonlinearsolver(model)

global newmodel

newmodel = 1;

model.dense = 0;
if ~(model.equalitypresolved || model.presolved)
    model = propagate_bounds_from_equalities(model);
end

K = model.K;
lb = model.lb;
ub = model.ub;
x0 = model.x0;
c = model.c;

% Pick out the positive conditions from cones ||Ax+b|| <= c'*x+d which will
% be treated as (Ax+b)'*(ax+b) <= (c'*x+d)^2,  c'*x+d >= 0
model = bounds_from_cones_to_lp(model);

if isempty(model.evaluation_scheme)
    model = build_recursive_scheme(model);
end
model = compress_evaluation_scheme(model);

% Do some pre-calc to be used in calls from fmincon
nonlinearindicies = union(find(model.variabletype~=0),model.evalVariables);
linearindicies    = setdiff(find(model.variabletype==0),nonlinearindicies);
model.nonlinearindicies = nonlinearindicies;
model.linearindicies    = linearindicies;

model.Anonlinineq = [];
model.bnonlinineq = [];
model.Anonlineq = [];
model.bnonlineq = [];

% Extract linear and nonlinear equality constraints
if K.f>0
    Aeq = -model.F_struc(1:1:K.f,2:end);
    beq = model.F_struc(1:1:model.K.f,1);

    nonlinear_equalities_indicies = find(any(Aeq(:,nonlinearindicies),2));
    model.Anonlineq = Aeq(nonlinear_equalities_indicies,:);
    model.bnonlineq = beq(nonlinear_equalities_indicies);

    Aeq(nonlinear_equalities_indicies,:) = [];
    beq(nonlinear_equalities_indicies,:) = [];
    Aeq(:,nonlinearindicies) = [];
    model.F_struc(1:model.K.f,:) = [];
    model.K.f = 0;
else
    Aeq = [];
    beq = [];
end

% Find nonlinear eualities implied by lower and upper bounds
if ~isempty(ub) && ~isempty(lb)
    nonlinearequality = find(lb(nonlinearindicies) == ub(nonlinearindicies));
    if ~isempty(nonlinearequality)
        for i = 1:length(nonlinearequality)
          %  model.Anonlineq = [model.Anonlineq;eyev(length(c),nonlinearindicies(nonlinearequality(i)))'];
            model.Anonlineq = [model.Anonlineq;sparse(1,nonlinearindicies(nonlinearequality(i)),1,1,length(c))];
            model.bnonlineq = [model.bnonlineq;lb(nonlinearindicies(nonlinearequality(i)))];
        end
    end
end

% Extract linear and nonlinear inequality constraints
if any(model.K.l)
    A = -model.F_struc(1:model.K.l,2:end);
    b = model.F_struc(1:model.K.l,1);

    nonlinear_inequalities_indicies = find(any(A(:,nonlinearindicies),2));

    model.Anonlinineq = A(nonlinear_inequalities_indicies,:);
    model.bnonlinineq = b(nonlinear_inequalities_indicies);

    A(nonlinear_inequalities_indicies,:) = [];
    b(nonlinear_inequalities_indicies,:) = [];
    A(:,nonlinearindicies) = [];

    model.F_struc(1:model.K.l,:) = [];
    model.K.l = 0;
else
    A = [];
    b = [];
end

% This helps with robustness in bnb in some cases
x0candidate = zeros(length(c),1);
if ~isempty(lb) && ~isempty(ub)
    bounded = find(~isinf(lb) & ~isinf(ub));
    x0candidate(bounded) = (lb(bounded) + ub(bounded))/2;
    bounded_below = find(~isinf(lb) & isinf(ub));
    x0candidate(bounded_below) = lb(bounded_below) + 0.5;
    bounded_above = find(~isinf(lb) & isinf(ub));
    x0candidate(bounded_above) = lb(bounded_above) + 0.5;
end

if isempty(x0)
    x0 = x0candidate(linearindicies);
else
    if ~isempty(lb) && ~isempty(ub)
        x0((x0 < lb) | (x0 > ub)) = x0candidate((x0 < lb) | (x0 > ub));
    end
    x0 = x0(linearindicies);
end

if ~isempty(lb)
    lb = lb(linearindicies);
end
if ~isempty(ub)
    ub = ub(linearindicies);
end

lb_old = lb;
ub_old = ub;
[lb,ub,A,b] = remove_bounds_from_Ab(A,b,lb,ub);
[lb,ub,Aeq,beq] = remove_bounds_from_Aeqbeq(Aeq,beq,lb,ub);

if any(model.variabletype == 4)
    problematic = find(any(model.monomtable(:,linearindicies) < 0 ,1));
    if ~isempty(problematic)
        problematic = problematic(find(x0(problematic)==0));
        Oneisfeas = problematic(find(ub(problematic) > 1));
        x0(Oneisfeas) = 1;
    end

    problematic = find(any(model.monomtable(:,linearindicies)~=fix(model.monomtable(:,linearindicies)) ,1));
    lb(problematic) = max(lb(problematic),0);
end
x0(find(lb==ub)) = lb(find(lb==ub));

if size(A,1) == 0
    A = [];
end

if size(b,1) == 0
    b = [];
end

if size(Aeq,1) == 0
    Aeq = [];
end

if size(beq,1) == 0
    beq = [];
end

if model.presolveequalities
    if ~isempty(beq) &  (~model.equalitypresolved | ~(isequal(lb,lb_old) & isequal(ub,ub_old)))
        % This helps when there are artificial variables introduced to model
        % nonlinear operators such as log(2*x+1)
        p.F_struc = [beq -Aeq];
        p.K.f = size(beq,1);
        p.lb = lb;
        p.ub = ub;
        p.variabletype = zeros(1,length(lb));
        p.binary_variables = [];
        p.integer_variables = [];
        p = propagate_bounds_from_equalities(p);
        lb = p.lb;
        ub = p.ub;
    end
end

model.A = A;
model.b = b;
model.Aeq = Aeq;
model.beq = beq;
model.lb = lb;
model.ub = ub;
model.x0 = x0;

model = setup_fmincon_params(model);

% Check if all derivatives are available
model.derivative_available = 1;
for i = 1:length(model.evalMap)
    if isempty(model.evalMap{i}.properties.derivative)
        model.derivative_available = 0;
        break
    end
end

% Some precomputation of computational scheme for Jacobian
allA = [model.Anonlineq;model.Anonlinineq];
if anyCones(model.K)
    allA = [allA;model.F_struc(startofSOCPCone(model.K):end,2:end)];
end
requested = any(allA',2);
[i,j] = find((model.deppattern(find(requested),:)));
requested(j) = 1;
if ~isempty(model.evalMap)
    % Recursive stuff is only possible if we have evaluation-based
    % operators
    model.Crecursivederivativeprecompute = precomputeDerivative(model,requested);
end

% Some precomputation of computational scheme for gradient
requested = model.c | any(model.Q,2);
[i,j,k] = find((model.deppattern(find(requested),:)));
requested(j) = 1;
model.frecursivederivativeprecompute = precomputeDerivative(model,requested);

% Precomputed list of bilinear expressions, used in
% apply_recursive_differentiation
model = compile_bilinearslist(model);
model = compile_quadraticslist(model);

model.binary_variables  = find(ismember(linearindicies,model.binary_variables));
model.integer_variables  = find(ismember(linearindicies,model.integer_variables));
model.semicont_variables  = find(ismember(linearindicies,model.semicont_variables));


classdef TestTransientAreasSegmentationModule
    %TestTransientAreasSegmentationModule

    properties (Constant)
        filename = fullfile(mexopencv.root(),'test','balloon.jpg');
    end

    methods (Static)
        function test_run
            img = cv.imread(TestTransientAreasSegmentationModule.filename, 'Color',true);
            sz = [size(img,2) size(img,1)];

            retina = cv.Retina(sz);
            retina.run(img);
            magno = retina.getMagnoRAW();

            seg = cv.TransientAreasSegmentationModule(sz);
            seg.clearAllBuffers();
            seg.run(magno);

            sz = seg.getSize();
            validateattributes(sz, {'numeric'}, {'vector', 'integer', 'numel',2});

            transientAreas = seg.getSegmentationPicture();
            validateattributes(transientAreas, {'uint8'}, {'size',[sz(2) sz(1)]});
            transientAreas = logical(transientAreas);
        end

        function test_params
            img = cv.imread(TestTransientAreasSegmentationModule.filename, 'Color',true);
            seg = cv.TransientAreasSegmentationModule([size(img,2) size(img,1)]);

            fname = [tempname() '.xml'];
            cObj = onCleanup(@() TestTransientAreasSegmentationModule.deleteFile(fname));
            seg.write(fname);
            seg.setup(fname);

            seg.setupParameters('LocalEnergyTemporalConstant',0.5);

            str = seg.printSetup();
            validateattributes(str, {'char'}, {'row', 'nonempty'});

            params = seg.getParameters();
            validateattributes(params, {'struct'}, {'scalar'});
        end
    end

    %% helper functions
    methods (Static)
        function deleteFile(fname)
            if exist(fname, 'file') == 2
                delete(fname);
            end
        end
    end

end


function [obSlice,reflections] = mrReflectObl(obSlice,obSize,reflections,which,update)
%
%NAME:	 [obSlice,reflections] = mrReflectObl(obSlice,obSize,reflections,which,update)
%AUTHOR:  Poirson
%DATE:    08.09.96
%HISTORY  11.08.96 SPG added bool update
%BUGS:

global obwin volslimin2 volslimax2;

row = obSize(1);
col = obSize(2);

if which == 1
	% First entry tell us left/right flipping
	reflections(1) = reflections(1) * (-1.0);
	tmp = fliplr(reshape(obSlice,row,col));

elseif which == 2
	% Second entry tell us up/down flipping
	reflections(2) = reflections(2) * (-1.0);
	tmp = flipud(reshape(obSlice,row,col));
else
	disp('mrReflectObl: invalid case');
end
 obSlice = tmp(:)';

if (update == 1)
 figure(obwin);
 myShowImageVol(obSlice',obSize,max(obSlice)*get(volslimin2,'value'),max(obSlice)*get(volslimax2,'value'));
end

return


close all;
seqNames = {'14_14', '14_06', '14_20','13_29', '13_30', '13_31'};
jogTsteps = { [42:82], '', '', '', [165:185], [145:165]};

jobNames = {'SM+zDD+AnnealLin', 'SM+zDD', 'SM+cDD+AnnealLin', 'SM+cDD', 'Prior'};
jobIDs = [2134873 2134874 2134875 2134876 1515159];

EXPORT_DIR = '/home/mhughes/git/BPARHMM-NEW/figs/Mocap6/';
taskID = 1;

jj =0;
for jobID = jobIDs( [1 end] );
    jj = jj+1;
    ss = 0;
    for seqID = [1 5 6]
        ss = ss + 1;
        plotAlignedStateSeqSegment( jobID, taskID, seqNames{seqID}, jogTsteps{ seqID }  );

        fname = fullfile(EXPORT_DIR, sprintf('JogSegmentation_seq%d_%s', seqID, jobNames{jj}) );
        export_fig( fname, '-eps');
        fprintf( 'Exporting %s\n', fname );
    end
end


function bundle  =  readBDL(filename)
% READBDL Read mesh(es) from a .bdl bundle file
%
% bundle  =  readBDL(filename)
%
% Input:
%   filename  path to .bdl file
% Outputs:
%   bundle  struct containing mesh data

  function mesh = readBDLMeshChunk(fp)
  % read a mesh chunk from a file stream
  %
  % Usage:
  %    mesh = readMeshChunk( fp)
  %
  % mesh fields:
  % V  (required)  vertices
  % F              faces
  % col            colors
  % baseColor      a single color for the whole mesh
  % UV             uv coords

      magicID   = fread(fp, 1, 'uint32');
          chunkSize = fread(fp, 1,  'int64');
          nV        = fread(fp, 1, 'uint32');
          nF        = fread(fp, 1, 'uint32');
          nVperFace = fread(fp, 1, 'uint32');
          nCperPos  = fread(fp, 1, 'uint32');
          nCperUV   = fread(fp, 1, 'uint32');
          nCperCol  = fread(fp, 1, 'uint32');
          nCperNor  = fread(fp, 1, 'uint32');
          strip     = fread(fp, 1, 'uchar');
          mesh.baseColor = fread(fp, 4, 'float32');

          mesh.V   = fread(fp, [nCperPos,nV],'float32');
      mesh.V = mesh.V';
          mesh.UV  = fread(fp, [nCperUV,nV], 'float32');
      mesh.UV = mesh.V';
          mesh.col = fread(fp, [nCperCol,nV],'float32');
      mesh.col = mesh.col';
          if nCperNor ~= 0 && nCperNor ~= 3
            error('nCperNor has to be 0 or 3')
          end
          if nCperNor == 3
            mesh.nor = fread(fp, [nCperNor,nV],'float32');
        mesh.nor = mesh.nor';
          end
          mesh.F = fread(fp,  [nVperFace,nF],'uint32');
          mesh.F = mesh.F+1;
  end

  fp = fopen(filename,'r');
  if fp == -1
     error('could not open file')
  end

  chunk = 1;
  while ~feof(fp)
     magicID = fread(fp,1,'uint32');
     if feof(fp)
        break
     end
     bck =  -sizeof('uint32');
     fseek(fp, bck, 'cof');
     if magicID == 1
    bundle.meshes{chunk} = readBDLMeshChunk(fp);
    chunk = chunk+1;
     else
        chunkSize = fread(fp, 1, 'uint64');
        fseek(fp, chunkSize, 'cof');
     end
  end


% DEMHIGHFIVE1 Demonstration of hierarchical GP-LVM on walking and running data.
%
%	Description:
%

%	Copyright (c) 2007 Neil D. Lawrence
% 	demHighFive1.m version 1.1

if exist('diaryFile')
    diary(diaryFile)
end

% Fix seeds
randn('seed', 1e5);
rand('seed', 1e5);

hsvargplvm_init;

dataSetName = 'highFive';
capName = dataSetName;
capName(1) = upper(capName(1));
experimentNo = 1;
dirSep = filesep;
baseDir = datasetsDirectory;

%--- Load data
try
    load([baseDir 'dem' dataSetName]);
catch
    [void, errid] = lasterr;
    if strcmp(errid, 'MATLAB:load:couldNotReadFile');
        skelA = acclaimReadSkel([baseDir 'mocap' dirSep 'cmu' dirSep '20' dirSep '20.asf']);
        [YA, skelA] = acclaimLoadChannels([baseDir 'mocap' dirSep 'cmu' dirSep '20' dirSep '20_11.amc'], skelA);
        seqInd = [50:4:113 114:155 156:4:size(YA, 1)];
        YA = YA(seqInd, :);
        %    YA(:, [4:end]) = asind(sind(YA(:, [4:end])));
        skelB = acclaimReadSkel([baseDir 'mocap' dirSep 'cmu' dirSep '21' dirSep '21.asf']);
        [YB, skelB] = acclaimLoadChannels([baseDir 'mocap' dirSep 'cmu' dirSep '21' dirSep '21_11.amc'], skelB);
        YB = YB(seqInd, :);
        %    YB(:, [4:end]) = asind(sind(YB(:, [4:end])));
        save([baseDir 'dem' dataSetName], 'YA', 'YB', 'skelA', 'skelB', ...
            'seqInd');
    else
        error(lasterr);
    end
end

Yall{1} = YA;
Yall{2} = YB;
clear('YA','YB');

%-- Set up model
numberOfDatasets = length(Yall);
globalOpt.indPoints = min(globalOpt.indPoints, size(Yall{1},1));

%-- Load datasets
for i=1:numberOfDatasets
    Y = Yall{i};
    dims{i} = size(Y,2);
    N{i} = size(Y,1);
    indTr = globalOpt.indTr;
    if indTr == -1
        indTr = 1:N{i};
    end
    if ~exist('Yts')
        indTs = setdiff(1:size(Y,1), indTr);
        Yts{i} = Y(indTs,:);
    end
    Ytr{i} = Y(indTr,:);

    t{i} = linspace(0, 2*pi, size(Y, 1)+1)'; t{i} = t{i}(1:end-1, 1);
    timeStampsTraining{i} = t{i}(indTr,1); %timeStampsTest = t(indTs,1);
end

for i=2:numberOfDatasets
    if N{i} ~= N{i-1}
        error('The number of observations in each dataset must be the same!');
    end
end

clear('Y')

%%--- Optimise %%--------- TO FIX (from this point and below) (this is now taken from svargplvm)
options = svargplvmOptions(Ytr, globalOpt, labelsTrain);

if ~isempty(globalOpt.dynamicsConstrainType)
    for i=1:numberOfDatasets
        % Set up dynamcis (i.e. back-constraints) model
        optionsDyn{i}.type = 'vargpTime';
        optionsDyn{i}.inverseWidth=30;
        %   optionsDyn.vardistCovars = vardistCovarsMult;
        optionsDyn{i}.initX = globalOpt.initX;
        optionsDyn{i}.constrainType = globalOpt.dynamicsConstrainType;

        if exist('timeStampsTraining')
            optionsDyn{i}.t = timeStampsTraining;
        end
        if exist('labelsTrain') && ~isempty(labelsTrain)
            optionsDyn{i}.labels = labelsTrain;
        end
    end
else
    optionsDyn= [];
end

model = svargplvmModelCreate(Ytr, globalOpt, options, optionsDyn);
if exist('diaryFile')
    model.diaryFile = diaryFile;
end

model.globalOpt = globalOpt;
model.options = options;

%%%% TEMP
if exist('whiteVar')
    model.dynamics.kern.comp{2}.variance = whiteVar;
end
%%%%

% Force kernel computations
params = svargplvmExtractParam(model);
model = svargplvmExpandParam(model, params);

%%
%fprintf('# Median of vardist. covars: %d \n',median(median(model.vardist.covars)));
%fprintf('# Min of vardist. covars: %d \n',min(min(model.vardist.covars)));
%fprintf('# Max of vardist. covars: %d \n',max(max(model.vardist.covars)));

if displayIters
    model = svargplvmOptimiseModel(model);
else
    model = svargplvmOptimiseModelNoDisplay(model);
end

%--------

%%
colordef white
ax = hgplvmHierarchicalVisualise(model, visualiseNodes, [], [0.03 ...
    0.5 0.03 0.03])
tar = get(ax, 'cameratarget');
pos = get(ax, 'cameraposition');
newPos = tar + (rotationMatrix(0, -pi/8, 3*pi/2)*(pos - tar)')';
set(ax, 'cameraposition', newPos)
set(ax, 'xlim', [-20 25]);
set(ax, 'ylim', [-15 8])
set(ax, 'visible', 'off')


function out = spm_run_factorial_design(job)
% SPM job execution function - factorial design specification
% Input:
% job    - harvested job data structure (see matlabbatch help)
% Output:
% out    - struct variable containing the path of the saved SPM.mat
%__________________________________________________________________________
% Copyright (C) 2005-2014 Wellcome Trust Centre for Neuroimaging

% Will Penny
% $Id: spm_run_factorial_design.m 7739 2019-12-02 14:00:18Z guillaume $

%--------------------------------------------------------------------------
% This function configures the design matrix (describing the general
% linear model), data specification, and other parameters necessary for
% the statistical analysis. These parameters are saved in a
% configuration file (SPM.mat) in the current directory, and are
% passed on to spm_spm.m (via the Estimate button) which estimates the
% design. Inference on these estimated parameters is then handled by the
% SPM results section.
%
% This function, that sets up the necessary SPM structures, has been
% largely cannibalised from spm_spm_ui.m which we have retained for
% developmental continuity.
%
% It has in common with spm_spm_ui.m its use of the I factor matrix,
% the H,C,B,G design matrix partitions, the sF,sCFI,CFIforms,sCC,CCforms,
% sGXcalc,sGloNorm,sGMsca option definition variables and use of the
% functions spm_DesMtx.m, spm_meanby.m and spm_get_vc.m.
%
% It departs from spm_spm_ui.m in that it does not use the design
% definition data structure D. Also, it uses the new SPM.factor field,
% which for the case of full factorial designs, is used to automatically
% generate contrasts testing for main effects and interactions.
%
% This function departs from spm_spm_ui.m in that it does not provide
% the same menu of design options (these were hardcoded in D). Instead it
% provides a number of options for simple designs (1) One-sample t-test,
% (2) Two-sample t-test, (3) Paired t-test and (4) Multiple regression.
% Two facilities are provided for specifying more complicated designs
% (5) Full-factorial and (6) Flexible-factorial. These should be able to
% specify all design options (and more) that were available in SPM2.
% For each of these design types one can additionally specify regressors
% using the `covariates' option.
%
% Options (5) and (6) differ in the efficiency (eg. number of key
% strokes/button presses) with which a given design can be specified. For
% example, one-way ANOVAs can be specified using either option, but (5) is
% usually more efficient.
%
% Full-factorial designs
% ______________________
%
% This option is best used when you wish to test for all main effects and
% interactions in one-way, two-way or three-way ANOVAs.
%
% Design specification proceeds in 2 stages. Firstly, by creating new
% factors and specifying the number of levels and name for each.
% Nonsphericity, ANOVA-by-factor (for PET data) and scaling options (for
% PET data) can also be specified at this stage. Secondly, scans are
% assigned separately to each cell. This accomodates unbalanced designs.
%
% For example, if you wish to test for a main effect in the population
% from which your subjects are drawn and have modelled that effect at the
% first level using K basis functions (eg. K=3 informed basis functions)
% you can use a one-way ANOVA with K-levels. Create a single factor with K
% levels and then assign the data to each cell eg. canonical, temporal
% derivative and dispersion derivative cells, where each cell is assigned
% scans from multiple subjects.
%
% SPM will automatically generate the contrasts necessary to test for all
% main effects and interactions.
%
% Flexible-factorial designs
% __________________________
%
% In this option the design matrix is created a block at a time. You can
% decide whether you wish each block to be a main effect or a (two-way)
% interaction.
%
% This option is best used for one-way, two-way or three-way ANOVAs but
% where you do not wish to test for all possible main effects and
% interactions. This is perhaps most useful for PET where there is usually
% not enough data to test for all possible effects. Or for 3-way ANOVAs
% where you do not wish to test for all of the two-way interactions. A
% typical example here would be a group-by-drug-by-task analysis where,
% perhaps, only (i) group-by-drug or (ii) group-by-task interactions are
% of interest. In this case it is only necessary to have two-blocks in the
% design matrix - one for each interaction. The three-way interaction can
% then be tested for using a contrast that computes the difference between
% (i) and (ii).
%
% Design specification then proceeds in 3 stages. Firstly, factors are
% created and names specified for each. Nonsphericity, ANOVA-by-factor and
% scaling options can also be specified at this stage.
%
% Secondly, a list of scans is produced along with a factor matrix, I.
% This is an nscan x 4 matrix of factor level indicators (see xX.I below).
% The first factor must be 'replication' but the other factors can be
% anything. Specification of I and the scan list can be achieved in one
% of two ways (a) the 'Specify All' option allows I to be typed in at the
% user interface or (more likely) loaded in from the matlab workspace.
% All of the scans are then selected in one go. (b) the 'Subjects' option
% allows you to enter scans a subject at a time. The corresponding
% experimental conditions (ie. levels of factors) are entered at the same
% time. SPM will then create the factor matrix I. This style of interface
% is similar to that available in SPM2.
%
% Thirdly, the design matrix is built up a block at a time. Each block
% can be a main effect or a (two-way) interaction.
%
%--------------------------------------------------------------------------
%
% Variables saved in the SPM stucture:
%
% xY.VY         - nScan x 1 struct array of memory mapped images
%                 (see spm_vol for definition of the map structure)
% xX            - structure describing design matrix
% xX.I          - nScan x 4 matrix of factor level indicators
%                 I(n,i) is the level of factor i corresponding to image n
% xX.sF         - 1x4 cellstr containing the names of the four factors
%                 xX.sF{i} is the name of factor i
% xX.X          - design matrix
% xX.xVi        - correlation constraints for non-spericity correction
% xX.iH         - vector of H partition (condition effects) indices,
%                 identifying columns of X corresponding to H
% xX.iC         - vector of C partition (covariates of interest) indices
% xX.iB         - vector of B partition (block effects) indices
% xX.iG         - vector of G partition (nuisance variables) indices
% xX.name       - p x 1 cellstr of effect names corresponding to columns
%                 of the design matrix
%
% xC            - structure array of covariate details
% xC(i).rc      - raw (as entered) i-th covariate
% xC(i).rcname  - name of this covariate (string)
% xC(i).c       - covariate as appears in design matrix (after any scaling,
%                 centering of interactions)
% xC(i).cname   - cellstr containing names for effects corresponding to
%                 columns of xC(i).c
% xC(i).iCC     - covariate centering option
% xC(i).iCFI    - covariate by factor interaction option
% xC(i).type    - covariate type: 1=interest, 2=nuisance, 3=global
% xC(i).cols    - columns of design matrix corresponding to xC(i).c
% xC(i).descrip - cellstr containing a description of the covariate
%
% xGX           - structure describing global options and values
% xGX.iGXcalc   - global calculation option used
% xGX.sGXcalc   - string describing global calculation used
% xGX.rg        - raw globals (before scaling and such like)
% xGX.iGMsca    - grand mean scaling option
% xGX.sGMsca    - string describing grand mean scaling
% xGX.GM        - value for grand mean (/proportional) scaling
% xGX.gSF       - global scaling factor (applied to xGX.rg)
% xGX.iGC       - global covariate centering option
% xGX.sGC       - string describing global covariate centering option
% xGX.gc        - center for global covariate
% xGX.iGloNorm  - Global normalisation option
% xGX.sGloNorm  - string describing global normalisation option
%
% xM            - structure describing masking options
% xM.T          - Threshold masking value (-Inf=>None, real=>absolute,
%                 complex=>proportional (i.e. times global))
% xM.TH         - nScan x 1 vector of analysis thresholds, one per image
% xM.I          - Implicit masking (0=>none, 1=>implicit zero/NaN mask)
% xM.VM         - struct array of explicit mask images
%                 (empty if no explicit masks)
% xM.xs         - structure describing masking options
%                 (format is same as for xsDes described below)
%
% xsDes         - structure of strings describing the design:
%                 Fieldnames are essentially topic strings (use "_"'s for
%                 spaces), and the field values should be strings or cellstr's
%                 of information regarding that topic. spm_DesRep.m
%                 uses this structure to produce a printed description
%                 of the design, displaying the fieldnames (with "_"'s
%                 converted to spaces) in bold as topics, with
%                 the corresponding text to the right
%
%--------------------------------------------------------------------------

%-Output directory
%--------------------------------------------------------------------------
cwd = pwd;
d   = spm_file(job.dir{1},'cpath');
if ~exist(d,'dir')
    sts = mkdir(d);
    if ~sts, error('Error creating output directory "%s".',d); end
end
cd(d);

%-Ask about overwriting files from previous analyses...
%--------------------------------------------------------------------------
if exist(fullfile(job.dir{1},'SPM.mat'),'file')
    str = { 'Current directory contains existing SPM file:',...
        'Continuing will overwrite existing file!'};
    if spm_input(str,1,'bd','stop|continue',[1,0],1,mfilename)
        fprintf('%-40s: %30s\n\n',...
            'Abort...   (existing SPM file)',spm('time'));
        return
    end
end

% If we've gotten to this point we're committed to overwriting files.
% Delete them so we don't get stuck in spm_spm
%--------------------------------------------------------------------------
files = {'^mask\..{3}$','^ResMS\..{3}$','^RPV\..{3}$',...
    '^beta_.{4}\..{3}$','^con_.{4}\..{3}$','^ResI_.{4}\..{3}$',...
    '^ess_.{4}\..{3}$', '^spm\w{1}_.{4}\..{3}$'};

for i=1:length(files)
    j = spm_select('List',pwd,files{i});
    for k=1:size(j,1)
        spm_unlink(deblank(j(k,:)));
    end
end

%-Option definitions
%==========================================================================

%-Generic factor names
%--------------------------------------------------------------------------
sF = {'sF1','sF2','sF3','sF4'};

%-Covariate by factor interaction options
sCFI = {'<none>';...                                        %-1
    'with sF1';'with sF2';'with sF3';'with sF4';...         %-2:5
    'with sF2 (within sF4)';'with sF3 (within sF4)'};       %-6,7

%-DesMtx argument components for covariate by factor interaction options
% (Used for CFI's Covariate Centering (CC), GMscale & Global normalisation)
%--------------------------------------------------------------------------
CFIforms = {'[]',   'C',    '{}';...                        %-1
    'I(:,1)',       'FxC',  '{sF{1}}';...                   %-2
    'I(:,2)',       'FxC',  '{sF{2}}';...                   %-3
    'I(:,3)',       'FxC',  '{sF{3}}';...                   %-4
    'I(:,4)',       'FxC',  '{sF{4}}';...                   %-5
    'I(:,[4,2])',   'FxC',  '{sF{4},sF{2}}';...             %-6
    'I(:,[4,3])',   'FxC',  '{sF{4},sF{3}}' };              %-7

%-Centre (mean correction) options for covariates & globals            (CC)
% (options 9-12 are for centering of global when using AnCova GloNorm) (GC)
%--------------------------------------------------------------------------
sCC = {'around overall mean';...                            %-1
    'around sF1 means';...                                  %-2
    'around sF2 means';...                                  %-3
    'around sF3 means';...                                  %-4
    'around sF4 means';...                                  %-5
    'around sF2 (within sF4) means';...                     %-6
    'around sF3 (within sF4) means';...                     %-7
    '<no centering>';...                                    %-8
    'around user specified value';...                       %-9
    '(as implied by AnCova)';...                            %-10
    'GM';...                                                %-11
    '(redundant: not doing AnCova)'}';                      %-12

%-DesMtx I forms for covariate centering options
%--------------------------------------------------------------------------
CCforms = {'ones(nScan,1)',CFIforms{2:end,1},''}';

%-Global calculation options                                       (GXcalc)
%--------------------------------------------------------------------------
sGXcalc  = {'omit';...                                      %-1
    'user specified';...                                    %-2
    'mean voxel value (within per image fullmean/8 mask)'}; %-3

%-Global normalization options                                    (GloNorm)
%--------------------------------------------------------------------------
sGloNorm = {'AnCova';...                                    %-1
    'AnCova by sF1';...                                     %-2
    'AnCova by sF2';...                                     %-3
    'AnCova by sF3';...                                     %-4
    'AnCova by sF4';...                                     %-5
    'AnCova by sF2 (within sF4)';...                        %-6
    'AnCova by sF3 (within sF4)';...                        %-7
    'proportional scaling';...                              %-8
    '<no global normalisation>'};                           %-9

%-Grand mean scaling options                                        (GMsca)
% (NB: Grand mean scaling by subject is redundent for proportional scaling)
%--------------------------------------------------------------------------
sGMsca = {'scaling of overall grand mean';...               %-1
    'scaling of sF1 grand means';...                        %-2
    'scaling of sF2 grand means';...                        %-3
    'scaling of sF3 grand means';...                        %-4
    'scaling of sF4 grand means';...                        %-5
    'scaling of sF2 (within sF4) grand means';...           %-6
    'scaling of sF3 (within sF4) grand means';...           %-7
    '(implicit in PropSca global normalisation)';...        %-8
    '<no grand Mean scaling>'   };                          %-9

%-Conditions of no interest defaults
%--------------------------------------------------------------------------
B      = [];
Bnames = {};
factor = [];

switch char(fieldnames(job.des))

    %-One sample t-test
    %======================================================================
    case 't1',

        DesName = 'One sample t-test';

        P = job.des.t1.scans;
        n = length(P);
        I = (1:n)';
        I = [I,ones(n,3)];

        [H,Hnames] = spm_DesMtx(I(:,2),'-','mean');

        factor(1).name     = 'Group';
        factor(1).levels   = 1;
        factor(1).variance = 0;
        factor(1).dept     = 0;

    %-Two-sample t-test
    %======================================================================
    case 't2',

        DesName = 'Two-sample t-test';

        P  = job.des.t2.scans1;
        n1 = length(job.des.t2.scans1);
        P  = [P; job.des.t2.scans2];
        n2 = length(job.des.t2.scans2);

        I  = [(1:n1),(1:n2)]';
        I  = [I,[ones(n1,1);2*ones(n2,1)]];
        I  = [I,ones(n1+n2,2)];

        [H,Hnames] = spm_DesMtx(I(:,2),'-','Group');

        % Names and levels
        factor(1).name     = 'Group';
        factor(1).levels   = 2;

        % Ancova options
        factor(1).gmsca    = job.des.t2.gmsca;
        factor(1).ancova   = job.des.t2.ancova;

        % Nonsphericity options
        factor(1).variance = job.des.t2.variance;
        factor(1).dept     = job.des.t2.dept;

        if any([n1 n2]==1) && factor(1).variance == 1
            warning('Imposing equal variance between groups for 1 vs N comparison.');
            factor(1).variance = 0;
        end

    %-Paired t-test
    %======================================================================
    case 'pt',

        DesName = 'Paired t-test';

        Npairs  = length(job.des.pt.pair);
        P       = [];
        for p   = 1:Npairs
            P   = [P;job.des.pt.pair(p).scans];
        end

        I       = ones(Npairs*2,1);
        I(:,2)  = kron([1:Npairs]',ones(2,1));
        I(:,3)  = kron(ones(Npairs,1),[1 2]');
        I(:,4)  = I(:,1);

        [B,Bnames] = spm_DesMtx(I(:,2),'-','Subject');
        [H,Hnames] = spm_DesMtx(I(:,3),'-','Condition');

        % Names and levels
        factor(1).name     = 'Subject';
        factor(1).levels   = Npairs;
        factor(2).name     = 'Condition';
        factor(2).levels   = 2;

        % Ancova options
        factor(1).gmsca    = 0;
        factor(1).ancova   = 0;
        factor(2).gmsca    = job.des.pt.gmsca;
        factor(2).ancova   = job.des.pt.ancova;

        % Nonsphericity options
        factor(1).variance = 0;
        factor(1).dept     = 0;
        factor(2).variance = 0;
        factor(2).dept     = 0;

    %-Multiple regression
    %======================================================================
    case 'mreg',

        DesName = 'Multiple regression';

        P = job.des.mreg.scans;
        n = length(P);
        I = (1:n)';
        I = [I,ones(n,3)];

        % Names and levels
        factor(1).name     = '';
        factor(1).levels   = 1;

        % Nonsphericity options
        factor(1).variance = 0;
        factor(1).dept     = 0;

        if job.des.mreg.incint==0
            H = []; Hnames = '';
        else
            [H,Hnames] = spm_DesMtx(I(:,2),'-','mean');
        end

        for i=1:length(job.des.mreg.mcov)
            job.cov(end+1).c   = job.des.mreg.mcov(i).c;
            job.cov(end).cname = job.des.mreg.mcov(i).cname;
            job.cov(end).iCC   = job.des.mreg.mcov(i).iCC;
            job.cov(end).iCFI  = 1;
        end

    %-ANOVA
    %======================================================================
    case 'anova',

        DesName = 'ANOVA';

        job.des.anova.fact.name = 'Groups';

        % Automatically number cells 1 to levels, so user doesn't have to
        levels = length(job.des.anova.icell);
        job.des.anova.fact.levels = levels;
        for i=1:levels
            job.des.anova.icell(i).levels = i;
        end
        [I,P,H,Hnames] = spm_design_factorial(job.des.anova);

        % Names and levels
        factor(1).name     = 'Groups';
        factor(1).levels   = levels;

        % Ancova options
        factor(1).gmsca    = job.des.anova.gmsca;
        factor(1).ancova   = job.des.anova.ancova;

        % Nonsphericity options
        factor(1).variance = job.des.anova.variance;
        factor(1).dept     = job.des.anova.dept;

    %-ANOVA: within-subject
    %======================================================================
    case 'anovaw',

        DesName = 'ANOVA - within subject';

        anovaw  = job.des.anovaw;
        anovaw.fac(1).name      = 'Subject';
        anovaw.fac(1).dept      = 0;
        anovaw.fac(1).variance  = 0;
        anovaw.fac(1).gmsca     = 0;
        anovaw.fac(1).ancova    = 0;

        anovaw.fac(2).name      = 'Groups';
        anovaw.fac(2).dept      = job.des.anovaw.dept;
        anovaw.fac(2).variance  = job.des.anovaw.variance;
        anovaw.fac(2).gmsca     = job.des.anovaw.gmsca;
        anovaw.fac(2).ancova    = job.des.anovaw.ancova;

        anovaw.fsuball.fsubject = anovaw.fsubject;

        % Main effect of subject and group
        anovaw.maininters{1}.fmain.fnum = 1;
        anovaw.maininters{2}.fmain.fnum = 2;

        [I,P,job.cov] = spm_design_within_subject(anovaw,job.cov);

        [H,Hnames,B,Bnames] = spm_design_flexible(anovaw,I);

        factor           = anovaw.fac;
        factor(1).levels = length(job.des.anovaw.fsubject);

    %-Full Factorial Design
    %======================================================================
    case 'fd',

        DesName = 'Full factorial';

        [I,P,H,Hnames] = spm_design_factorial(job.des.fd);

        Nfactors = length(job.des.fd.fact);
        for i=1:Nfactors
            % Names and levels
            factor(i).name     = job.des.fd.fact(i).name;
            factor(i).levels   = job.des.fd.fact(i).levels;

            % Ancova options
            factor(i).gmsca    = job.des.fd.fact(i).gmsca;
            factor(i).ancova   = job.des.fd.fact(i).ancova;

            % Nonsphericity options
            factor(i).variance = job.des.fd.fact(i).variance;
            factor(i).dept     = job.des.fd.fact(i).dept;
        end

    %-Flexible factorial design
    %======================================================================
    case 'fblock',

        DesName = 'Flexible factorial';

        if isfield(job.des.fblock.fsuball,'fsubject')
            % Data has been entered subject by subject
            nf = length(job.des.fblock.fac);
            [I,P,job.cov] = spm_design_within_subject(job.des.fblock,job.cov);
        else
            % Specify all scans and factor matrix
            I = job.des.fblock.fsuball.specall.imatrix;
            [ns,nI] = size(I);
            % Pad out factorial matrix to cover the four canonical factors
            if nI < 4
                warning('Padding factor matrix to have four columns.');
                I = [I, ones(ns,4-nI)];
            end
            % Get number of factors
            nf = length(job.des.fblock.fac);
            P  = job.des.fblock.fsuball.specall.scans;
        end

        if isempty(job.des.fblock.maininters)
            warning('No main effects or interactions have been specified.');
        end
        [H,Hnames,B,Bnames] = spm_design_flexible(job.des.fblock,I);

        for i=1:nf
            % Names and levels
            factor(i).name     = job.des.fblock.fac(i).name;
            factor(i).levels   = length(unique(I(:,i+1)));

            % Ancova options
            factor(i).gmsca    = job.des.fblock.fac(i).gmsca;
            factor(i).ancova   = job.des.fblock.fac(i).ancova;

            % Nonsphericity options
            factor(i).variance = job.des.fblock.fac(i).variance;
            factor(i).dept     = job.des.fblock.fac(i).dept;
        end

end

nScan = size(I,1);

%-Covariate partition(s): interest (C) & nuisance (G) excluding global
%==========================================================================
dstr = {'covariate','nuisance variable'};
C  = []; Cnames = {};                 %-Covariate DesMtx partitions & names
G  = []; Gnames = {};

xC = [];                              %-Struct array to hold raw covariates

%-Multiple covariates
%--------------------------------------------------------------------------
for m=1:numel(job.multi_cov)
    for n=1:numel(job.multi_cov(m).files)
        tmp   = load(job.multi_cov(m).files{n});
        names = {};
        if isstruct(tmp) % .mat
            if isfield(tmp,'R')
                R = tmp.R;
                if isfield(tmp,'names')
                    names = tmp.names;
                end
            else
                error(['Variable ''R'' not found in multiple ' ...
                    'covariates file ''%s''.'], job.multi_cov(m).files{n});
            end
        elseif isnumeric(tmp) % .txt
            R     = tmp;
            % read names from first line if commented?
        end
        for j=1:size(R,2)
            job.cov(end+1).c   = R(:,j);
            if isempty(names)
                job.cov(end).cname = sprintf('R%d%s',j);
            else
                job.cov(end).cname = names{j};
            end
            job.cov(end).iCFI  = job.multi_cov(m).iCFI;
            job.cov(end).iCC   = job.multi_cov(m).iCC;
        end
    end
end

%-Covariates
%--------------------------------------------------------------------------
nc = length(job.cov);                 %-Number of covariates
for i=1:nc

    c      = job.cov(i).c;
    cname  = job.cov(i).cname;
    rc     = c;                       %-Save covariate value
    rcname = cname;                   %-Save covariate name
    if job.cov(i).iCFI==1
        iCFI=1;
    else
        % SPMs internal factor numbers are 1 higher than specified in user
        % interface as, internally, the first factor is always `replication'
        iCFI = job.cov(i).iCFI+1;
    end
    switch job.cov(i).iCC
        case 1
            iCC = 1;
        case {2,3,4}
            iCC = job.cov(i).iCC + 1;
        otherwise
            iCC = job.cov(i).iCC + 3;
    end

    %-Centre within factor levels as appropriate
    if any(iCC == (1:7))
        c = c - spm_meanby(c,eval(CCforms{iCC}));
    end

    %-Do any interaction (only for single covariate vectors)
    %----------------------------------------------------------------------
    if iCFI > 1                       %-(NB:iCFI=1 if size(c,2)>1)
        tI        = [eval(CFIforms{iCFI,1}),c];
        tConst    = CFIforms{iCFI,2};
        tFnames   = [eval(CFIforms{iCFI,3}),{cname}];
        [c,cname] = spm_DesMtx(tI,tConst,tFnames);
    elseif size(c,2)>1                %-Design matrix block
        [null,cname] = spm_DesMtx(c,'X',cname);
    else
        cname     = {cname};
    end

    %-Store raw covariate details in xC struct for reference
    %-Pack c into appropriate DesMtx partition
    %----------------------------------------------------------------------
    %-Construct description string for covariate
    str = {sprintf('%s',rcname)};
    if size(rc,2)>1, str = {sprintf('%s (block of %d covariates)',...
            str{:},size(rc,2))}; end
    if iCC < 8, str=[str;{['used centered ',sCC{iCC}]}]; end
    if iCFI> 1, str=[str;{['fitted as interaction ',sCFI{iCFI}]}]; end

    typ = 1;
    tmp = struct(...
        'rc',   rc,    'rcname', rcname,...
        'c',    c,     'cname',  {cname},...
        'iCC',  iCC,   'iCFI',   iCFI,...
        'type', typ,...
        'cols', [1:size(c,2)] + size([H,C],2) + size([B,G],2)*min(typ-1,1),...
        'descrip', {str});
    if isempty(xC), xC = tmp; else xC = [xC,tmp]; end
    C     = [C,c];
    Cnames = [Cnames; cname];

end
clear c tI tConst tFnames

%==========================================================================
% - C O N F I G U R E   D E S I G N -
%==========================================================================

%-Images & image info: Map Y image files and check consistency of
% dimensions and orientation / voxel size
%==========================================================================
fprintf('%-40s: ','Mapping files')                                      %-#
VY    = spm_data_hdr_read(char(P));

%-Check compatibility of images
%--------------------------------------------------------------------------
spm_check_orientations(VY);

fprintf('%30s\n','...done')                                             %-#

%-Global values, scaling and global normalisation
%==========================================================================
%-Compute global values
%--------------------------------------------------------------------------
switch char(fieldnames(job.globalc))
    case 'g_omit',
        iGXcalc = 1;
    case 'g_user',
        iGXcalc = 2;
    case 'g_mean',
        iGXcalc = 3;
end

switch job.globalm.glonorm
    case 1,
        iGloNorm = 9;
    case 2,
        iGloNorm = 8;
    case 3,
        iGloNorm = 1;
end
if factor(1).levels > 1
    % Override if factor-specific ANCOVA has been specified
    for i=1:length(factor)
        if factor(i).ancova
            iGloNorm=i+2;
        end
    end
end

%-Analysis threshold mask
%--------------------------------------------------------------------------
%-Work out available options:
% -Inf=>None, real=>absolute, complex=>proportional, (i.e. times global)
M_T = -Inf;
switch char(fieldnames(job.masking.tm)),
    case 'tma',
        % Absolute
        M_T = job.masking.tm.tma.athresh;
    case 'tmr',
        % Relative
        M_T = job.masking.tm.tmr.rthresh*sqrt(-1);
        % Need to force calculation of globals
        if iGXcalc~=2, iGXcalc=3; end
    case 'tm_none'
        % None
        M_T = -Inf;
end

if iGXcalc==1 && (any(iGloNorm == [1:5 8]) || ...
        (factor(1).levels > 1 && any([factor.gmsca])))
    % Over-ride omission of global calculation if we need it
    disp(' ');
    disp('SPM needs estimates of global activity.');
    disp('But you have specified to omit this computation.');
    disp('SPM has overridden this omission and will automatically compute ');
    disp('globals as the mean value of within brain voxels.');
    disp(' ');
    iGXcalc = 3;
end
sGXcalc = sGXcalc{iGXcalc};

switch iGXcalc,
    case 1
        %-Don't compute => no GMsca (iGMsca==9) or GloNorm (iGloNorm==9)
        g = [];
    case 2
        %-User specified globals
        g = job.globalc.g_user.global_uval;
    case 3
        %-Compute as mean voxel value (within per image fullmean/8 mask)
        g = zeros(nScan,1);
        fprintf('%-40s: %30s','Calculating globals',' ')                %-#
        for i = 1:nScan
            str = sprintf('%3d/%-3d',i,nScan);
            fprintf('%s%30s',repmat(sprintf('\b'),1,30),str)            %-#
            g(i) = spm_global(VY(i)); % FIXME % for meshes
        end
        fprintf('%s%30s\n',repmat(sprintf('\b'),1,30),'...done')        %-#
    otherwise
        error('illegal iGXcalc')
end
rg = g;

fprintf('%-40s: ','Design configuration')                               %-#

%-Grand mean scaling options                                        (GMsca)
%--------------------------------------------------------------------------
if iGloNorm==8
    iGMsca=8;   %-grand mean scaling implicit in PropSca GloNorm
else
    switch char(fieldnames(job.globalm.gmsca))
        case 'gmsca_yes',
            iGMsca=1;
        case 'gmsca_no',
            iGMsca=9;
    end
    if factor(1).levels > 1
        % Over-ride if factor-specific scaling has been specified
        for i=1:numel(factor)
            if factor(i).gmsca
                iGMsca=i+2;
            end
        end
    end
end

%-Value for PropSca / GMsca                                            (GM)
%--------------------------------------------------------------------------
switch iGMsca,
    case 9                                %-Not scaling (GMsca or PropSca)
        GM = 0;                           %-Set GM to zero when not scaling
    case 1                                %-Ask user value of GM
        GM = job.globalm.gmsca.gmsca_yes.gmscv;
    otherwise
        if iGloNorm==8
            switch char(fieldnames(job.globalm.gmsca))
                case 'gmsca_yes',
                    % Proportionally scale to this value
                    GM = job.globalm.gmsca.gmsca_yes.gmscv;
                case 'gmsca_no',
                    GM = 50;
            end
        else
            % Grand mean scaling by factor eg. scans are scaled so that the
            % mean global value over each level of the factor is set to GM
            GM=50;
        end
end

%-If GM is zero then don't GMsca! or PropSca GloNorm
if GM==0,
    iGMsca=9;
    if iGloNorm==8,
        iGloNorm=9;
    end
end

%-Sort out description strings for GloNorm and GMsca
%--------------------------------------------------------------------------
sGloNorm = sGloNorm{iGloNorm};
sGMsca   = sGMsca{iGMsca};
if iGloNorm==8
    sGloNorm = sprintf('%s to %-4g',sGloNorm,GM);
elseif iGMsca<8
    sGMsca   = sprintf('%s to %-4g',sGMsca,GM);
end

%-Scaling: compute global scaling factors gSF required to implement
% proportional scaling global normalisation (PropSca) or grand mean
% scaling (GMsca), as specified by iGMsca (& iGloNorm)
%--------------------------------------------------------------------------
switch iGMsca,
    case 8
        %-Proportional scaling global normalisation
        if iGloNorm~=8, error('iGloNorm-iGMsca(8) mismatch for PropSca'), end
        gSF    = GM./g;
        g      = GM*ones(nScan,1);
    case {1,2,3,4,5,6,7}
        %-Grand mean scaling according to iGMsca
        if iGXcalc==1, error('Global calculation option is not appropriate.'), end
        gSF    = GM./spm_meanby(g,eval(CCforms{iGMsca}));
        g      = g.*gSF;
    case 9
        %-No grand mean scaling
        gSF    = ones(nScan,1);
    otherwise
        error('illegal iGMsca')
end

%-Apply gSF to memory-mapped scalefactors to implement scaling
%--------------------------------------------------------------------------
for i = 1:nScan
    VY(i).pinfo(1:2,:) = VY(i).pinfo(1:2,:)*gSF(i); % FIXME % for meshes
end

%-Global centering (for AnCova GloNorm)                                (GC)
%-If not doing AnCova then GC is irrelevant
%--------------------------------------------------------------------------
if ~any(iGloNorm == [1:7])
    iGC = 12;
    gc  = [];
else
    iGC = 10;
    gc = 0;
end

%-AnCova: Construct global nuisance covariates partition (if AnCova)
%--------------------------------------------------------------------------
if any(iGloNorm == [1:7])

    %-Centre global covariate as requested
    %----------------------------------------------------------------------
    switch iGC, case {1,2,3,4,5,6,7}    %-Standard sCC options
        gc = spm_meanby(g,eval(CCforms{iGC}));
        case 8                  %-No centering
            gc = 0;
        case 9                  %-User specified centre
            %-gc set above
        case 10                 %-As implied by AnCova option
            gc = spm_meanby(g,eval(CCforms{iGloNorm}));
        case 11                 %-Around GM
            gc = GM;
        otherwise               %-unknown iGC
            error('unexpected iGC value')
    end

    %-AnCova - add scaled centred global to DesMtx `G' partition
    %----------------------------------------------------------------------
    rcname     = 'global';
    tI         = [eval(CFIforms{iGloNorm,1}),g - gc];
    tConst     = CFIforms{iGloNorm,2};
    tFnames    = [eval(CFIforms{iGloNorm,3}),{rcname}];
    [f,gnames]  = spm_DesMtx(tI,tConst,tFnames);
    clear tI tConst tFnames

    %-Save GX info in xC struct for reference
    %----------------------------------------------------------------------
    str     = {sprintf('%s: %s',dstr{2},rcname)};
    if any(iGMsca==[1:7]), str=[str;{['(after ',sGMsca,')']}]; end
    if iGC ~= 8, str=[str;{['used centered ',sCC{iGC}]}]; end
    if iGloNorm > 1
        str=[str;{['fitted as interaction ',sCFI{iGloNorm}]}];
    end
    tmp  = struct(  'rc',rg.*gSF,       'rcname',rcname,...
        'c',f,          'cname' ,{gnames},...
        'iCC',iGC,      'iCFI'  ,iGloNorm,...
        'type',         3,...
        'cols',[1:size(f,2)] + size([H C B G],2),...
        'descrip',      {str}       );

    G = [G,f]; Gnames = [Gnames; gnames];
    if isempty(xC), xC = tmp; else xC = [xC,tmp]; end

elseif iGloNorm==8 || iGXcalc>1

    %-Globals calculated, but not AnCova: Make a note of globals
    %----------------------------------------------------------------------
    if iGloNorm==8
        str = { 'global values: (used for proportional scaling)';...
            '("raw" unscaled globals shown)'};
    elseif isfinite(M_T) && ~isreal(M_T)
        str = { 'global values: (used to compute analysis threshold)'};
    else
        str = { 'global values: (computed but not used)'};
    end

    rcname ='global';
    tmp     = struct('rc',rg,    'rcname',rcname,...
        'c',{[]},   'cname' ,{{}},...
        'iCC',0,    'iCFI'  ,0,...
        'type',     3,...
        'cols',     {[]},...
        'descrip',  {str}           );

    if isempty(xC), xC = tmp; else xC = [xC,tmp]; end
end

%-Save info on global calculation in xGX structure
%--------------------------------------------------------------------------
xGX = struct(...
    'iGXcalc', iGXcalc,  'sGXcalc', sGXcalc,  'rg',rg,...
    'iGMsca',  iGMsca,   'sGMsca',  sGMsca,   'GM',GM,    'gSF',gSF,...
    'iGC',     iGC,      'sGC',     sCC{iGC}, 'gc',gc,...
    'iGloNorm',iGloNorm, 'sGloNorm',sGloNorm);

%-Make a description string
%--------------------------------------------------------------------------
if isinf(M_T)
    xsM.Analysis_threshold = 'None (-Inf)';
elseif isreal(M_T)
    xsM.Analysis_threshold = sprintf('images thresholded at %6g',M_T);
else
    xsM.Analysis_threshold = sprintf(['images thresholded at %6g ',...
        'times global'],imag(M_T));
end

%-Construct masking information structure and compute actual analysis
% threshold using scaled globals (rg.*gSF)
%--------------------------------------------------------------------------
if isreal(M_T),
    M_TH = M_T  * ones(nScan,1);    %-NB: -Inf is real
else
    M_TH = imag(M_T) * (rg.*gSF);
end

%-Implicit masking: Ignore zero voxels in low data-types?
%--------------------------------------------------------------------------
% (Implicit mask is NaN in higher data-types.)
if ~spm_type(VY(1).dt(1),'nanrep')
    M_I = job.masking.im;  % Implicit mask ?
    if M_I
        xsM.Implicit_masking = 'Yes: zero''s treated as missing';
    else
        xsM.Implicit_masking = 'No';
    end
else
    M_I = 1;
    xsM.Implicit_masking = 'Yes: NaN''s treated as missing';
end

%-Explicit masking
%--------------------------------------------------------------------------
if isempty(job.masking.em{:})
    VM = [];
    xsM.Explicit_masking = 'No';
else
    VM = spm_data_hdr_read(char(job.masking.em));
    xsM.Explicit_masking = 'Yes';
end

xM     = struct('T',M_T, 'TH',M_TH, 'I',M_I, 'VM',{VM}, 'xs',xsM);

%-Construct full design matrix (X), parameter names and structure (xX)
%==========================================================================
X      = [H C B G];
tmp    = cumsum([size(H,2), size(C,2), size(B,2), size(G,2)]);
xX     = struct(...
    'X',        X,...
    'iH',       [1:size(H,2)],...
    'iC',       [1:size(C,2)] + tmp(1),...
    'iB',       [1:size(B,2)] + tmp(2),...
    'iG',       [1:size(G,2)] + tmp(3),...
    'name',     {[Hnames; Cnames; Bnames; Gnames]},...
    'I',        I,...
    'sF',       {sF});

%-Design description (an nx2 cellstr) - for saving and display
%==========================================================================
tmp = {sprintf('%d condition, +%d covariate, +%d block, +%d nuisance',...
    size(H,2),size(C,2),size(B,2),size(G,2));...
    sprintf('%d total, having %d degrees of freedom',...
    size(X,2),rank(X));...
    sprintf('leaving %d degrees of freedom from %d images',...
    size(X,1)-rank(X),size(X,1))};
xsDes = struct('Design',    {DesName},...
    'Global_calculation',   {sGXcalc},...
    'Grand_mean_scaling',   {sGMsca},...
    'Global_normalisation', {sGloNorm},...
    'Parameters',           {tmp});

fprintf('%30s\n','...done')                                             %-#

%-Generate error covariance components (non-sphericity)
%==========================================================================
Vi          = spm_get_vc(I, factor);

%-Assemble SPM structure
%==========================================================================
SPM.xY.P    = P;            % filenames
SPM.xY.VY   = VY;           % mapped data
SPM.nscan   = size(xX.X,1); % scan number
SPM.xX      = xX;           % design structure
SPM.xC      = xC;           % covariate structure
SPM.xGX     = xGX;          % global structure
SPM.xM      = xM;           % mask structure
SPM.xsDes   = xsDes;        % description
SPM.xVi.I   = I;            % factor matrix
if numel(Vi) == 1
    SPM.xVi.V  = Vi{1};     % non-sphericity matrix
else
    SPM.xVi.Vi = Vi;        % non-sphericity variance components
end

%-Automatic contrast generation for 'Full factorial'
%--------------------------------------------------------------------------
if strcmp(char(fieldnames(job.des)),'fd') && job.des.fd.contrasts
    SPM.factor = factor;
end

%-Save SPM.mat and set output argument
%--------------------------------------------------------------------------
fprintf('%-40s: ','Saving SPM configuration')                           %-#
fmt = spm_get_defaults('mat.format');
s = whos('SPM');
if s.bytes > 2147483647, fmt = '-v7.3'; end
save('SPM.mat', 'SPM', fmt);
fprintf('%30s\n','...SPM.mat saved')                                    %-#

out.spmmat{1} = fullfile(pwd, 'SPM.mat');

%-Display Design report
%==========================================================================
if ~spm('CmdLine') && ~isempty(spm_figure('FindWin','Graphics'))
    fprintf('%-40s: ','Design reporting')                               %-#
    fname     = cat(1,{SPM.xY.VY.fname}');
    spm_DesRep('DesMtx',SPM.xX,fname,SPM.xsDes)
    fprintf('%30s\n','...done')                                         %-#
end

fprintf('%-40s: %30s\n','Completed',spm('time'))                        %-#

%-Change back directory
%--------------------------------------------------------------------------
cd(cwd);


function [struct_irf_record D_record gamma_record hd_record ETA_record IVcorrelation PofIVcorrelation beta_gibbs_reshuffle sigma_gibbs_reshuffle]=irfres_zeros_magn_correl_fevd_bayesian_stvol4(beta_gibbs, sigma_gibbs, It, Bu,betahat,sigmahat,IRFperiods,n,m,p,k,T,signrestable,signresperiods, relmagnrestable, relmagnresperiods, names, startdate, enddate, ShockwithInstrument, Ycycle, Xcycle, signreslabels, FEVDresperiods, FEVDrestable, data_exo, HD, const, exo, InstrumentforCorrel, IRFt, YincLags, Psi_gibbs, pref)
%betahat = betahatcycle                                                                                irfres_zeros_magn_correl_fevd_bayesian_stvol4(beta_gibbs, sigma_gibbs, It, Bu,betahatcycle,sigmahatcycle,IRFperiods,n,m,p,k,T,signrestable,signresperiods, relmagnrestable, relmagnresperiods, namespostratining, startdateposttraining, enddate, strctident.ShockwithInstrument, Ycycle, Xcycle, signreslabels, FEVDresperiods, FEVDrestable,data_exo, HD, 0, exo, strctident.InstrumentforCorrel, IRFt, YincLags);
%sigmahat = sigmahatcycle
%names =namespostraining
%startdate = startdateposttraining
%ShockwithInstrument =  strctident.ShockwithInstrument
%InstrumentforCorrel = strctident.InstrumentforCorrel

% inputs:  - matrix 'betahat': OLS estimate for beta
%          - matrix 'sigmahats': OLS estimate for sigma
%          - integer 'IRFperiods': number of periods for IRFs
%          - integer 'n': number of endogenous variables in the BVAR model (defined p 7 of technical guide)
%          - integer 'm': number of exogenous variables in the BVAR model (defined p 7 of technical guide)
%          - integer 'p': number of lags included in the model (defined p 7 of technical guide)
%          - integer 'k': number of coefficients to estimate for each equation in the BVAR model (defined p 7 of technical guide)
%          - cell 'signrestable': table recording the sign restriction input from the user
%          - cell 'signresperiods': table containing the periods corresponding to each restriction
%          - string 'ShockwithInstrument' Name of the shock where the instrument belongs to
% outputs: - cell 'struct_irf_record': record of the gibbs sampler draws for the orthogonalised IRFs
%          - matrix 'D_record': record of the gibbs sampler draws for the structural matrix D
%          - matrix 'gamma_record': record of the gibbs sampler draws for the structural disturbances variance-covariance matrix gamma
%          - integer 'Qdraw': total number of draws of the Q matrix
%          - integer 'Qsuccess': number of successful draws of the Q matrix

tic

%%Phase 1: Preliminary tasks

%% draw from VAR posterior
%sample beta and sigma from the VAR distribution centered around the OLS estimate
inv_sigma_hat = inv(sigmahat); %invert sigmahat as it is frequently used afterwards
Acc=It-Bu; %%number of minimum draws accepted

%% Preliminiaries for sign restrictions
% now identify all the periods concerned with restrictions
% first expand the non-empty entries in signresperiods since they are only expressed in intervals: transform into list
% for instance, translate [1 4] into [1 2 3 4]; I don't think this can done without a loop
temp=cell2mat(signresperiods(~cellfun(@isempty,signresperiods)));
periods=[];
for ii=1:size(temp,1)
    periods=[periods temp(ii,1):temp(ii,2)];
end
% suppress duplicates and sort
periods=sort(unique(periods))';
% count the total number of restriction periods (required for IRF matrix)
nperiods=size(periods,1);

% Identify the restriction matrices
% create five cells, corresponding to the three possible restrictions:
% one cell for sign restrictions, three cells for magnitude restrictions, one cell for zero restrictions
Scell=cell(1,n);
Mcell=cell(1,n);
Mlcell=cell(1,n);
Mucell=cell(1,n);
Zcell=cell(1,n);

% Check if value and periods restrictions correspond to each other
if sum(sum(~cellfun(@isempty,signresperiods) == ~cellfun(@isempty,signrestable))) == n^2
    % All cells with sign restrictions also specify the horizon over which
    % these are applied
else
    disp('Warning: Value restrictions do not correspond to period restrictions one to one')
    pause(1)
end

% loop over rows and columns of the period matrix
for ii=1:n
    for jj=1:n
        % if entry (ii,jj) of the period matrix and of the value matrix is not empty...
        if ~isempty(signresperiods{ii,jj}) && ~isempty(signrestable{ii,jj})
            % ... then there is a restriction over one (or several) periods
            % loop overt those periods
            for kk=signresperiods{ii,jj}(1,1):signresperiods{ii,jj}(1,2)
                % identify the position of the considered period within the list of all periods (required to build the matrix)
                position=find(periods==kk);
                % now create the restriction matrix: this will depend on the type of restriction
                % if it is a positive sign restriction...
                if strcmp(signrestable{ii,jj},'+')
                    % ... then input a 1 entry in the corresponding S matrix
                    Scell{1,jj}=[Scell{1,jj};zeros(1,n*nperiods)];
                    Scell{1,jj}(end,(position-1)*n+ii)=1;
                    % if it is a negative sign restriction...
                elseif strcmp(signrestable{ii,jj},'-')
                    % ... then input a -1 entry in the corresponding S matrix
                    Scell{1,jj}=[Scell{1,jj};zeros(1,n*nperiods)];
                    Scell{1,jj}(end,(position-1)*n+ii)=-1;
                    % if it is a zero restriction...
                elseif strcmp(signrestable{ii,jj},'0')
                    % ... then input a 1 entry in the corresponding Z matrix
                    Zcell{1,jj}=[Zcell{1,jj};zeros(1,n*nperiods)];
                    Zcell{1,jj}(end,(position-1)*n+ii)=1;
                    % else, a non-empty entry being neither a sign nor a zero restriction has to be a magnitude restriction
                else
                    % fill the corresponding M matrices:
                    % input a 1 in M
                    Mcell{1,jj}=[Mcell{1,jj};zeros(1,n*nperiods)];
                    Mcell{1,jj}(end,(position-1)*n+ii)=1;
                    % input the lower value of the interval in Ml
                    temp=str2num(signrestable{ii,jj});
                    Mlcell{1,jj}=[Mlcell{1,jj};temp(1,1)];
                    % input the upper value of the interval in Mu
                    Mucell{1,jj}=[Mucell{1,jj};temp(1,2)];
                end
            end
        end
    end
end

%% Preliminaries for relative magnitude restrictions
% now identify all the periods concerned with relative magnitude
% restrictions
% first expand the non-empty entries in magresperiods since they are only expressed in intervals: transform into list
% for instance, translate [1 4] into [1 2 3 4];
temp=cell2mat(relmagnresperiods(~cellfun(@isempty,relmagnresperiods)));
mperiods=[];
for ii=1:size(temp,1)
    mperiods=[mperiods temp(ii,1):temp(ii,2)];
end
% suppress duplicates and sort
mperiods=sort(unique(mperiods))';
% count the total number of restriction periods (required for IRF matrix)
rmperiods=size(periods,1);

%create matrix entry for relative magnitude restrictions
[r clm] = find(~cellfun('isempty',relmagnrestable));
%2. Indentify which entry corresponds to the positive magnitude
%restriction (which shock is supposed to have a larger impact on which
%variable)
num_magres=length(r)/2; %number of relative magnitude restrictions
IndextempL=double.empty;
kk=1; %number of the restrictions
IndextempS=double.empty;
kk=1; %%number of restriction

rowsS = [];
columnsS = [];
for jj=1:num_magres %%loop over number of magnitude restrictions
    strtemp = strcat('S',num2str(jj)); %%find entry in the table corresponding to the Stronger than restriction
    Stronger = strcmp(relmagnrestable, strtemp);
    [rowS columnS] = find(Stronger==1);
    rowsS = [rowsS rowS];
    columnsS = [columnsS columnS];
end

rowsW = [];
columnsW = [];
for jj=1:num_magres
    strtemp = strcat('W',num2str(jj));
    Weaker = strcmp(relmagnrestable, strtemp);
    [rowW columnW] = find(Weaker==1);
    rowsW = [rowsW rowW];
    columnsW = [columnsW columnW];
end

%% Preliminiaries for IV correlation restrictions
%%load the instrument
ShockwithIV = find(contains(signreslabels,ShockwithInstrument)); %find index for the Shock with correlation restriction

% check for correlation restrictions
if isempty(ShockwithIV)%when there is no shock with an extra instrument
    IVcorrelcheck=0; %there is noting to check
    IVcorrelation=nan(Acc,1); %empty vector such that the paralel loop doesnt crash
    IVcorrel=nan(T,1); %empty vector such that the paralel loop doesnt crash
    PofIVcorrelation=nan(Acc,1); %empty vector such that the paralel loop doesnt crash
    ETA_record=nan(Acc,1); %empty vector such that the paralel loop doesnt crash
    IVcorrel='noexist'; %empty vector such that the paralel loop doesnt crash
    OverlapIVcorrelinY='noexist';%empty vector such that the paralel loop doesnt crash
    Flipcorrel=0; %there is nothing to flip
else
    IVcorrelcheck=1;
end
if IVcorrelcheck==1
    [IVcorrel txtcorrel]=xlsread(pref.excelFile,'IV');

    Index = strcmp(txtcorrel(1,:), InstrumentforCorrel);           %find the instrument in the IV sheet
    IVnum = find(Index==1, 1, 'first')-1;
    IVcorrel = IVcorrel(:, IVnum);
    IVcorrel = IVcorrel(~isnan(IVcorrel));
    txtcorrel = txtcorrel(2:length(IVcorrel)+1,1);              % drop IV names from txt
    date = names(2:end,1);                                   %get the datevector of the VAR
    startlocationY_in_Y=find(strcmp(date,startdate));        %location of sample startdate in Y datevector
    endlocationY_in_Y=find(strcmp(date,enddate));            %location of sample enddate in Y datevector
    date = date(startlocationY_in_Y+p:endlocationY_in_Y,:);  %cut datevector of Y such that it corresponds to the time dates used in the VAR
    OverlapIVcorrelinY = ismember(date,txtcorrel);           %Use this to cut EPS
    OverlapYinIVcorrel = ismember(txtcorrel,date);           %Use this to cut IV
    IVcorrel = IVcorrel(OverlapYinIVcorrel,:);               %cut all the entries from IV that are not in the sample
end

IsNotIdentified = find(contains(signreslabels,'shock'));        %find not identified shock
IsIdentified = find(~contains(signreslabels,'shock'));    %
if min(IsNotIdentified)==0
    identified=n;
else
    identified=min(IsNotIdentified)-1;                              %number of identified shocks
end

%finally check if there are sign restrictions on the shock of interest. If
%not we can use the flipped entry of the rotation matrix aswell
if ~isempty(ShockwithIV)
    if isempty(Scell{1,ShockwithIV})
        FlipCorrel=1;
    else
        FlipCorrel=0;
    end
end

%% Preliminaries for FEVD restriction
% now identify all the periods concerned with FEVD restrictions
% first expand the non-empty entries in FEVDresperiods since they are only expressed in intervals: transform into list
% for instance, translate [1 4] into [1 2 3 4];
temp=cell2mat(FEVDresperiods(~cellfun(@isempty,FEVDresperiods)));
FEVDperiods=[];
for ii=1:size(temp,1)
    FEVDperiods=[FEVDperiods temp(ii,1):temp(ii,2)];
end
% suppress duplicates and sort
FEVDperiods=sort(unique(FEVDperiods))';
% count the total number of restriction periods (required for IRF matrix)
FEVDperiodstot=size(FEVDperiods,1);

%create matrix entry for relative magnitude restrictions
[rowsFEVD clmFEVD] = find(~cellfun('isempty',FEVDrestable));
num_FEVDres=length(rowsFEVD); %number of FEVD restrictions

%check if rows are unique. Two FEVD restrictions for one variable are not
%included in the algorithm. Two columns (shocks) are fine.
uniquerows = unique(rowsFEVD);

if length(uniquerows) < length(rowsFEVD)
    error('Two FEVD restrictions for one variable are not permitted')
end

%now identify if the FEVD restrictions are absolute ones or relative ones
numrelativeFEVD =0;
numabsoluteFEVD =0;
for kk=1:num_FEVDres
    if strcmp(FEVDrestable{rowsFEVD(kk,1),clmFEVD(kk,1)},'Relative')==1
        numrelativeFEVD=numrelativeFEVD+1;
        rowrelativeFEVD(kk,1)=rowsFEVD(kk,1); %rows are the variables for the FEVD
        clmrelativeFEVD(kk,1)=clmFEVD(kk,1);%Columns are the variables for the FEVD
    elseif strcmp(FEVDrestable{rowsFEVD(kk,1),clmFEVD(kk,1)},'Absolute')==1
        numabsoluteFEVD=numabsoluteFEVD+1;
        rowabsoluteFEVD(kk,1)=rowsFEVD(kk,1);%rows are the variables for the FEVD
        clmabsoluteFEVD(kk,1)=clmFEVD(kk,1); %Columns are the variables for the FEVD
    end
end

%if no restriction of one kind exist,set empty cells
if numabsoluteFEVD ==0
    rowabsoluteFEVD = [];
    clmabsoluteFEVD = [];
end

if numrelativeFEVD ==0
    rowrelativeFEVD = [];
    clmrelativeFEVD = [];
end

%% preliminaries for historical decomposition
contributors = n + 1 + 1 + length(exo); %variables + constant + exogenous + initial conditions
hd_estimates2=cell(contributors+2,n); %shocks+constant+initial values+exogenous+unexplained+to be explained by shocks only

%% Check kind of restrictions
% now check what kind of restrictions apply among sign, zero and magnitude restrictions
% check for sign restrictions: if there are any, at least one entry in the cell Scell is non-empty
if sum(~cellfun(@isempty,Scell))~=0
    signres=1;
else
    signres=0;
end
% similarly check for zero restrictions
if sum(~cellfun(@isempty,Zcell))~=0
    zerores=1;
else
    zerores=0;
end
% check for absolute magnitude restrictions
if sum(~cellfun(@isempty,Mcell))~=0
    magnres=1;
else
    magnres=0;
end
% check for relative magnitude restrictions
if length(columnsS)~=0
    relmagnres=1;
else
    relmagnres=0;
end
% check for correlation restrictions
if isempty(ShockwithIV)%when there is no shock with an extra instrument
    IVcorrelcheck=0;
else
    IVcorrelcheck=1;
end
% check for FEVD restrictions
if numabsoluteFEVD ==0 && numrelativeFEVD==0 %when there are no absolute and no relative FEVD restrictions
    FEVDcheck=0;
else
    FEVDcheck=0;
end

%%Activate the restriction, that unidentified shocks should not have the
%%same pattern as identified
patterncheck=0;
%%activate the possibility of absolute relative magnitude restriction
%%(i.e. credit spreads should rise by more than interest rates fall)
%%--> abs(credit spread) > abs(interes rate) instead of
%%--> credit spread>interest rate
ABS=0;

%% Storage cells
% create first the cell that will store the results from the simulations
struct_irf_record=cell(n,n);
% storage cell
storage1=cell(Acc,1);
storage2=cell(Acc,1);
storage3=cell(Acc,1);
storage4=cell(Acc,1);
In= eye(n);

% initiate rotation draws
not_successful = 0;
hbar = bear.parfor_progressbar(Acc,'Progress of Sign, Magnitude, Zero, Correlation and FEVD Restriction Draws');  %create the progress bar

%rearrange Psidraw such that it can be accessed in a parfor loop
for yyy=1:It-Bu
    for kkk=1:n
Psi_gibbs_new(:,kkk,yyy) = Psi_gibbs{1,kkk}(:,yyy);
    end
end

parfor ii=1:Acc
    % initiate the variable 'success'; this variable will be used to check whether the restrictions are satisfied
    % if there are only zero restrictions, they will be satisfied by construction, and 'success' will simply be ignored
    success=0;
    % how the algorithm will be conducted will depend on the types of restrictions implemented
    % if there are only zero restrictions, the algorithm is simple as no checking is required: the conditions are satisfied by construction
   if zerores==1 && signres==0 && magnres==0 && relmagnres==0
   % draw beta and sigma
   beta=beta_gibbs(:,ii);
   sigma=reshape(sigma_gibbs(:,ii),n,n);
   hsigma=chol(bear.nspd(sigma),'lower');
   % obtain orthogonalised IRFs
   [~, ortirfmatrix]=bear.irfsim(beta,hsigma,n,m,p,k,max(IRFperiods,max(periods)));
   % generate the stacked IRF matrix
   stackedirfmat=[];
      for kk=1:numel(periods)
      stackedirfmat=[stackedirfmat;ortirfmatrix(:,:,periods(kk,1)+1)];
      end
   % draw an entire random matrix Q satisfying the zero restrictions
   [Q]=bear.qzerores(n,Zcell,stackedirfmat);
   % there is no need to verify the restrictions: there are satisfied by construction

   % if there are sign/magnitude/correlation restrictions, possibly associated with zero restrictions
   else
        % the algorithm becomes a bit more complicated as conditions now need to be checked
        % to maintain efficiency, the algorithm proceeds recursively shock by shock, and stops as soon as a condition on the considered shock fails
        % repeat algorithm for the iteration as long as not all conditions are satisfied
        while success==0
            not_successful = not_successful+1;
            % switch 'success' to 1; it will be turned back to zero if at any time Q is detected as a candidate not satisfying the restrictions
            success=1;
            % draw randomly the vector of VAR coefficients: draw a random index
            index=floor(rand*(Acc))+1;
            % then draw a random set of beta and sigma corresponding to this index (this is done to make it possible to draw, if required, an infinite number of values from the gibbs sampler record, with equal probability on each value)
            beta=beta_gibbs(:,index);
            sigma=reshape(sigma_gibbs(:,index),n,n);
            hsigma=chol(bear.nspd(sigma),'lower');
            %also draw the corresponding local mean
            Psidraw = Psi_gibbs_new(:,:,index)
            %create the vector Ydraw by subtracting the local mean from the data
            Ypsi = YincLags(p+1:end,:)-Psidraw(p+1:end,:);
            %ultimately create the RHS and LHS of the demeaned data VAR
            temp=bear.lagx(Ypsi,p);
            % to build X, take off the n initial columns of current data
            Xdraw=[temp(:,n+1:end)];
            Ydraw=temp(:,1:n);
            % obtain orthogonalised IRFs
            [~, ortirfmatrix]=bear.irfsim(beta,hsigma,n,m,p,k,max(IRFperiods,max(periods)));
            % generate the stacked IRF matrix
            stackedirfmat=[];
            for kk=1:numel(periods)
                stackedirfmat=[stackedirfmat;ortirfmatrix(:,:,periods(kk,1)+1)];
            end

            % now start looping over the shocks and checking sequentially whether conditions on these shocks hold
            % stop as soon as one restriction fails
            okay = zeros(n,1); %initiate okay vector
            Qjstore = [];
            % initiate Qj
            Qj=[];
            jj=1;
            while success==1 && jj<=n && sum(okay)<n
                    % draw a random vector from the standard normal
                    if okay(1,1)==0 %first find the first column
                        qj=bear.qrandj(n,Zcell{1,jj},stackedirfmat,Qj);
                        % obtain the candidate column fj
                        fj=stackedirfmat*qj;
                        [success qj]=bear.checksignres(Scell{1,jj},qj,fj);
                        if success==1
                            Qjstore=[Qj qj];
                            Qj(:,1) = qj; %set column yy of Qj to qj
                            jj=1+1;
                            okay(1,1)=1;
                        end
                    else
                        x=normrnd(0,1,n,1);
                        qj=(In-Qjstore*Qjstore')*x/norm((In-Qjstore*Qjstore')*x);
                        %compute the rotated impulse responses
                        fj=stackedirfmat*qj;
                        [success, qj, okay, yy]=bear.checksignres_inc_other_shocks(qj, fj, Scell, okay, IRFt, n);
                        if success==1
                            Qjstore=[Qj qj];
                            Qj(:,yy) = qj; %set column yy of Qj to qj
                            jj=jj+1;
                        end
                    end

            %once all n columns are build and fullfill the sign restriction
            %% if sign and magnitude restrictions are fullfilled, check proxy correlation restriction
            if size(Qj,2)==n && success==1  && IVcorrelcheck==1
                %disp('I reached correlation restrictions')
                D=hsigma*Qj;
                % recover the VAR coefficients, reshaped for convenience
                B=reshape(beta,k,n);
                % obtain the residuals from (this draw)
                EPS=Ydraw-Xdraw*B;
                %compute structural shocks
                ETA=D\EPS';
                [success corIV pivShockwithIV Qj] = bear.CheckCorrelWithIV(ETA,n,ShockwithIV, IVcorrel,OverlapIVcorrelinY, FlipCorrel, Qj);
                if success==1
                    disp('correlation restriction fulfilled');
                end
            end
            %% check relative magnitudes
            if size(Qj,2)==n && success==1  && relmagnres==1
                %              disp('I reached magnitude restrictions')
                D=hsigma*Qj;
                [~, ortirfmatrixmagnitude]=bear.irfsim(beta,D,n,m,p,k,max(IRFperiods,max(mperiods)));
                % generate the stacked IRF matrix
                stackedirfmatmagn=[];
                for kk=1:numel(mperiods)
                    stackedirfmatmagn=[stackedirfmatmagn;ortirfmatrixmagnitude(:,:,mperiods(kk,1)+1)];
                end
                [success]=bear.checkrelmag(stackedirfmatmagn,columnsS, columnsW, rowsS, rowsW, n, mperiods, ABS);
                if success ==1
                    disp('Magnitude Restrictions fullfilled')
                end
            end

            %% if sign, zero and relative magnitude restrictions are fullfilled, check FEVD restrictions
            if size(Qj,2)==n && success==1  && FEVDcheck==1
                disp('I reached FEVD restrictions')
                D=hsigma*Qj; %again compute D
                [~,ortirfmatrixFEVD]=bear.irfsim(beta,D,n,m,p,k,IRFperiods); %obtain orthogonalized IRFs
                % record the results in the cell irf_record
                %check FEVDrestrictions
                [success] = bear.CheckFEVDrestriction(ortirfmatrixFEVD,IRFperiods,n,D,FEVDperiodstot, clmrelativeFEVD, rowrelativeFEVD, rowabsoluteFEVD, clmabsoluteFEVD, FEVDresperiods, rowsFEVD);
                if success==1
                    disp('FEVD restriction fulfilled');
                end
            end

            end
            %finally compute the historical decomposition
            if size(Qj,2)==n && success==1  && HD==1
                D=hsigma*Qj;
                B=reshape(beta,k,n);
                % obtain the residuals from (this draw)
                EPS=Ydraw-Xdraw*B;
                %compute structural shocks
                ETA=D\EPS';
                Psidrawcut = Psidraw(2*p:end,:);
                %decompose the data into trend and cycle and further
                [hd_estimates] = bear.hd_new_for_signres_stvol4(0,beta,k,n,p,D,m,T,Xdraw,Ydraw, data_exo, contributors, hd_estimates2, Psidrawcut, YincLags(2*p+1:end,:));
            end
            % repeat this loop until a succesful draw is obtained

        end %end of while loop ´
        % with succesful Qj at hand, eventually set Q as Qj
        Q=Qj;
   end %end of if loop
    % store
    for kk=1:IRFperiods
        storage1{ii,1}(:,:,kk)=ortirfmatrix(:,:,kk)*Q;
    end
    storage2{ii,1}=hsigma*Q;
    % store historical decompositions
    if HD==1
        storage3{ii,1}=hd_estimates;
        storage4{ii,1}=ETA;
    end
    storage5(:,ii) = beta;
    storage6(:,ii) = bear.vec(sigma);

    %lpdf = irfpdf(hsigma*Q,betahat,aux1,T,sigmahat,beta);
    %lpdfirf(ii,1)=lpdf;
    if IVcorrelcheck==1
        IVcorrelation(ii,1)=corIV;
        PofIVcorrelation(ii,1)=pivShockwithIV;
    else
        IVcorrelation(ii,1)=0;
        PofIVcorrelation(ii,1)=0;
    end
    %  FEVDrestrictionvalue(ii,1) = FEVDrestrictionvalue;
    hbar.iterate(1);   % update progress by one iteration
end
close(hbar);   %close progress bar

beta_gibbs_reshuffle = storage5; %save the reshuffled beta and sigma such that they correspond to the structural matrix D
sigma_gibbs_reshuffle = storage6;
% reorganise storage
% loop over iterations
for ii=1:Acc
    % loop over IRF periods
    for jj=1:IRFperiods
        % loop over variables
        for kk=1:n
            % loop over shocks
            for ll=1:n
                struct_irf_record{kk,ll}(ii,jj)=storage1{ii,1}(kk,ll,jj);
            end
        end
    end
    D_record(:,ii)=storage2{ii,1}(:);
    gamma_record(:,ii)=bear.vec(eye(n));
end
%reorganize historical decompositions
hd_record=cell(contributors+2,n);
if HD==1
    for ii=1:Acc %loop over draws
        for kk=1:contributors+2 %loop over contributors
            for ll=1:n %loop over variables
                hd_record{kk,ll}(ii,:) = storage3{ii,1}{kk,ll};
            end
        end
    end
end
ETA_record=cell(n,1);
if HD==1
    for jj=1:Acc
        for kk=1:n
            ETA_record{kk,1}(jj,:)= storage4{jj,1}(kk,:);
        end
    end
end

%hdrecord is ordered such that columns are variables and rows are contributors
%row n+1 = contribution of the constant
%row n+2 = contribution of initial conditions (past shocks)
%row n+3 = unexplained part (for partially identified model
%row n+4 = part that was left to explain by the structural shocks after
%accounting for exogenous, constant and initial conditions

toc
fprintf('Accepted Draws in Percent of Total Number of Draws: %f', 100*(Acc)/(not_successful + Acc))
end


clear all; close all;

addpath('../matlab/');

model_root_dir = 'DSC_removal_SDR/';
definition_file = [model_root_dir 'deploy.prototxt'];
binary_file = [model_root_dir 'snapshot/' 'DSC_iter_160000_lab.caffemodel'];

assert(exist(binary_file, 'file') ~= 0);
assert(exist(definition_file, 'file') ~= 0);

caffe.reset_all();

caffe.set_mode_gpu();
caffe.set_device(0);

% Initialize a network
net = caffe.Net(definition_file, binary_file, 'test');

%root_dir = '/home/xwhu/dataset/SRD/train_argu/shadow/';
% root_dir = '/home/xwhu/dataset/ISTD/train_argu/train_A/';
%imgFiles=dir([root_dir '*.jpg']);

root_dir = '/home/xwhu/dataset/SRD/test_data/shadow/';
image_list=textread('../../data/SRD/test.txt', '%s');
%root_dir = '/home/xwhu/dataset/ISTD/test/test_A/';
%image_list=textread('../../data/ISTD/test.txt', '%s');

save_root = [model_root_dir 'result/'];

if exist(save_root, 'dir') == 0
    mkdir(save_root);
end

%nImg=length(imgFiles);
nImg=length(image_list);

imgW = 400; imgH = 400;
scale = 0.0039212686;

usedtime = 0;
show = 0;

colorTransform = makecform('srgb2lab');
colorTransform2 = makecform('lab2srgb');

for k = 1 : nImg

    test_image = imread([root_dir image_list{k}]);
    %test_image = imread([root_dir imgFiles(k).name]);

    test_image = applycform(test_image, colorTransform);

    if (show)
        imshow(test_image);
    end

    ori_size = [size(test_image,1), size(test_image,2)];
    test_image = imresize(test_image,[imgH imgW]);
    test_image = single(test_image(:,:,[3 2 1]));
    test_image = test_image.*scale;
    test_image = permute(test_image, [2 1 3]);

    % network forward
    tic; outputs = net.forward({test_image}); pertime=toc;
    usedtime=usedtime+pertime; avgtime=usedtime/k;

    res_fuse = net.blobs('upscore-fuse').get_data();
    res_global = net.blobs('res_g').get_data();
    final = (res_fuse + res_global)./2;

    final = permute(final, [2 1 3]);
    final = final./scale;
    final = uint8(final(:,:,[3 2 1]));
    final = imresize(final, ori_size);

    final = applycform(final, colorTransform2);

    %imwrite(final,[save_root imgFiles(k).name]);
    imwrite(final,[save_root image_list{k}]);

    if (mod(k,100)==0), fprintf('idx %i/%i, avgtime=%.4fs\n',k,nImg,avgtime); end

end

fprintf('idx %i/%i, avgtime=%.4fs\n',k,nImg,avgtime);


function output = bnb_solvelower(lowersolver,relaxed_p,upper,lower,x_min,allSolutions)

if all(relaxed_p.lb==relaxed_p.ub)
    x = relaxed_p.lb;
    if checkfeasiblefast(relaxed_p,relaxed_p.lb,relaxed_p.options.bnb.feastol)
        output.problem = 0;
    else
        output.problem = 24;
    end
    output.Primal = x;
    return
end

if ~(relaxed_p.all_integers && all(relaxed_p.c == fix(relaxed_p.c)) && nnz(relaxed_p.Q)==0)
     % Objective contains floating-point numbers, so add some margin
     % if we add an upper bound cut
     upper = upper + 1e-4;
end

p = relaxed_p;
p.solver.tag = p.solver.lower.tag;

if ~isinf(upper) && nnz(p.Q)==0 && isequal(p.K.m,0) && ~any(p.variabletype)
    if p.all_integers && all(p.c == fix(p.c))
        % All integer objective coefficients and all integer
        % variables, we must find a solution which is at least
        % 1 better than current upper bound
        if upper == lower + 1
            p = addEquality(p,[upper-1-p.f -p.c']);
        else
            p = addInequality(p,[upper-1-p.f -p.c']);
        end
    end
end

if ~isinf(upper) && p.all_integers && all(p.ub <= 0) && all(p.lb >= -1)
    % Exclusion cuts for negated binaries based on some optimal solutions
    % kept for historical reason on malformed model
    for i = 1:min(size(allSolutions,2),10)
        [b,a] = exclusionCut(allSolutions(:,end-i+1),-1);
        p = addInequality(p,[b a]);
    end
elseif ~isinf(upper) && p.all_integers && all(p.ub <= 1) && all(p.lb >= 0)
    % Normal exclusion on binary
     for i = 1:min(size(allSolutions,2),10)
         [b,a] = exclusionCut(allSolutions(:,end-i+1),1);
         p = addInequality(p,[b a]);
     end
end

% for i = 1:length(p.cardinalityvariables)
%     used = p.cardinalityvariables{i};
%     L = p.lb(used);
%     if sum(L) == p.cardinalitysize{i}
%         p.ub(used(p.lb(used) < p.ub(used) )) = 0;
%     end
% end

removethese = p.lb==p.ub;
[~,map] = ismember(find(~p.lb==p.ub),1:length(p.c));
if nnz(removethese)>0 && all(p.variabletype == 0) && isempty(p.evalMap) && p.options.allowsmashing

    % Fixed variables, so let us try to presolve as muh as possible
    % (needed often in SDPs etc where solvers are less robust to weird
    % models having no interior etc)
    p = smashFixed(p,'delete');
    p = smashQPOjective(p,removethese);
    idx = find(removethese);

    % FIX: should be updated
    % safe fix now where we just remove
    p.cardinalityvariables = [];
    p.cardinalitygroups = [];
    %p.atmost.groups = [];
    %p = smashAtmost(p,idx);

    p.lb(idx)=[];
    p.ub(idx)=[];
    if ~isempty(p.x0)
        p.x0(idx)=[];
    end
    p.monomtable(:,idx)=[];
    p.monomtable(idx,:)=[];
    p.variabletype(idx) = [];

    [p,infeasible] = detectRedundantInfeasibleSOCPRows(p);
    if infeasible
        output = createOutputStructure(24);
        return
    end

    [p,infeasible] = detectRedundantInfeasibleSDPRows(p);
    if infeasible
        output = createOutputStructure(24);
        return
    end

    [p,infeasible] = detectRedundantInfeasibleEXPRows(p);
    if infeasible
        output = createOutputStructure(24);
        return
    end

    [p,infeasible] = detectRedundantInfeasiblePOWRows(p);
    if infeasible
        output = createOutputStructure(24);
        return
    end

    % We do this last, as the SOCP/EXP/SDP presolve might add trivial
    % equalities from presolving 0 >= norm(z) etc
    p = removeEmptyLPRows(p);
    [p,infeasible] = detectRedundantInfeasibleLPRows(p);
    if infeasible
        output = createOutputStructure(24);
        return
    end

    % Derive bounds from this presolved model, and if we detect new fixed
    % variables, apply recursively
    if ~isempty(p.F_struc)
        [lb,ub] = find_lp_bounds(p.F_struc,p.K,p.lb,p.ub,1);
        p.ub = min(ub,p.ub);
        p.lb = max(lb,p.lb);
    end

    if any(p.lb > p.ub)
        output = createOutputStructure(24);
        return
    end

    if any(p.lb == p.ub)
        % Recurse!
        output = bnb_solvelower(lowersolver,p,inf,lower,x_min,[]);
    elseif any(p.lb > p.ub-p.options.bnb.feastol)
        % Infeasible
        output = createOutputStructure(24);
        return
    else
        % Solve relaxation
        p.solver.version = p.solver.lower.version;
        p.solver.subversion = p.solver.lower.subversion;
        output = feval(lowersolver,p);
    end
    if output.problem == 1 || output.problem == 24
        output.Primal = [];
        return
    end
    % Recover
    x=relaxed_p.c*0;
    x(removethese)=relaxed_p.lb(removethese);
    x(~removethese)=output.Primal;
    output.Primal=x;
else
    p.solver = p.solver.lower;
    output = feval(lowersolver,p);
end