function D = spm_eeg_average_TF(S)
% Average each channel over trials or trial types, for time-frequency data
% FORMAT D = spm_eeg_average_TF(S)
%
% S         - optional input struct
%    fields of S:
% S.D           - MEEG object or filename of M/EEG mat-file with epoched TF data
% S.circularise - flag that indicates whether average is straight (0) or
%                 vector (1) of phase angles.
% S.robust      - (optional) - use robust averaging (only for power)
%                 .savew  - save the weights in an additional dataset
%                 .bycondition - compute the weights by condition (1,
%                                default) or from all trials (0)
%                 .ks     - offset of the weighting function (default: 3)
%
% Output:
% D         - MEEG object (also written to disk).
%__________________________________________________________________________
% Copyright (C) 2008-2017 Wellcome Trust Centre for Neuroimaging

% Stefan Kiebel
% $Id: spm_eeg_average_TF.m 7125 2017-06-23 09:49:29Z guillaume $

SVNrev = '$Rev: 7125 $';

%-Startup
%--------------------------------------------------------------------------
spm('FnBanner', mfilename, SVNrev);
spm('FigName','M/EEG TF averaging'); spm('Pointer','Watch');

if ~isfield(S, 'circularise'),       S.circularise = 0;          end

%-Configure robust averaging
%--------------------------------------------------------------------------
if isstruct(S.robust)
    if ~isfield(S.robust, 'savew'),        S.robust.savew =  0;        end
    if ~isfield(S.robust, 'bycondition'),  S.robust.bycondition = 0;   end
    if ~isfield(S.robust, 'ks'),           S.robust.ks =  3;           end

    robust      = 1;
    savew       = S.robust.savew;
    bycondition = S.robust.bycondition;
    ks          = S.robust.ks;
    removebad   = S.robust.removebad;
else
    robust = 0;
end

%-Get MEEG object
%--------------------------------------------------------------------------
D = spm_eeg_load(S.D);

%-Check data type
%--------------------------------------------------------------------------
if ~strcmp(D.type, 'single')
    error('This function can only be applied to single trial data');
end

if ~strncmp(D.transformtype, 'TF', 2) % TF and TFphase
    error('This function can only be applied to time-frequency data.');
end

if strcmp(D.transformtype, 'TFphase')
    if ~isequal(S.robust, 0)
        warning('Robust averaging is not applicable to phase data and will not be used.');
        S.robust = 0;
    end
    plv = S.circularise;
end

%-Generate new MEEG object with new files
%--------------------------------------------------------------------------
Dnew = clone(D, [S.prefix fname(D)], [D.nchannels D.nfrequencies D.nsamples D.nconditions]);

if robust && savew
    Dw = clone(D, ['W' fname(D)]);
end

cl   = D.condlist;

ni = zeros(1,D.nconditions);
for i = 1:D.nconditions
    w = indtrial(D, deblank(cl{i}), 'GOOD');
    ni(i) = length(w);
    if ni(i) == 0
        warning('%s: No trials for trial type %s', D.fname, cl{i});
    end
end

goodtrials  =  indtrial(D, cl, 'GOOD');

if robust && removebad
    bad     = badsamples(D, ':', ':', ':');
end

spm_progress_bar('Init', D.nsamples, 'Samples completed');
if D.nsamples > 100, Ibar = floor(linspace(1, D.nsamples, 100));
else Ibar = [1:D.nsamples]; end
for j = 1:D.nsamples
     if robust && ~bycondition
         Y       = D(:, :, j, goodtrials);
         if removebad
             ibad = reshape(bad(:, j, goodtrials), [size(bad, 1), 1, 1, length(goodtrials)]);
             ibad = repmat(ibad, [1, D.nfrequencies, 1, 1]);
             Y(ibad) = NaN;
         end
         [Y, W1] = spm_robust_average(Y, 4, ks);

         if savew
             Dw(:, :, j, goodtrials) = W1;
         end
         W = zeros([D.nchannels D.nfrequencies 1 D.ntrials]);
         W(:, :, 1, goodtrials) = W1;
     end
    for i = 1:D.nconditions

        w = indtrial(D, deblank(cl{i}), 'GOOD');

         if isempty(w)
             continue;
         end

        %-Straight average
        %------------------------------------------------------------------
        if ~strcmp(D.transformtype, 'TFphase')
            if ~robust
                Dnew(:, :, j, i) = mean(D(:, :, j, w), 4);
             else
                 if bycondition
                     Y      = D(:, :, j, w);
                     if removebad
                         ibad = reshape(bad(:, j, w), [size(bad, 1), 1, 1, length(w)]);
                         ibad = repmat(ibad, [1, D.nfrequencies, 1, 1]);
                         Y(ibad) = NaN;
                     end
                     [Y, W] = spm_robust_average(Y, 4, ks);
                     Dnew(:, :, j, i) = Y;
                     if savew
                         Dw(:, :, j, w)   = W;
                     end
                 else
                     X = D(:, :, j, w);
                     X(isnan(X))      = 0;
                     Dnew(:, :, j, i) = ...
                         sum(W(:, :, 1, w).*X, 4)./sum(W(:, :, 1, w), 4);
                 end
            end

            %-Vector average (eg PLV for phase)
            %--------------------------------------------------------------
        else
            tmp = D(:, :, j, w);
            tmp = exp(sqrt(-1)*tmp);
            if plv
                Dnew(:, :, j, i) = abs(mean(tmp,4));
            else
                Dnew(:, :, j, i) = angle(mean(tmp,4));
            end
        end
    end
    if ismember(j, Ibar), spm_progress_bar('Set', j); end
end

spm_progress_bar('Clear');

Dnew = type(Dnew, 'evoked');

%-Update some header information
%--------------------------------------------------------------------------
Dnew = conditions(Dnew, ':', cl);
Dnew = repl(Dnew, ':', ni);

%-Display averaging statistics
%--------------------------------------------------------------------------
fprintf('%s: Number of replications per contrast:\n', Dnew.fname);      %-#
for i = 1:D.nconditions
    fprintf('  average %s: %d trials\n', cl{i}, ni(i));                 %-#
end

%-Save new evoked M/EEG dataset
%--------------------------------------------------------------------------
Dnew = Dnew.history('spm_eeg_average', S);
save(Dnew);

if robust && savew
    Dw = Dw.history('spm_eeg_average', S);
    save(Dw);
end

D = Dnew;

%-Cleanup
%--------------------------------------------------------------------------
fprintf('%-40s: %30s\n','Completed',spm('time'));                       %-#
spm('FigName','M/EEG TF averaging: done'); spm('Pointer', 'Arrow');


function boundaryBenchHtml(baseDir)
% function boundaryBenchHtml(baseDir)
%
% See also boundaryBench, boundaryBenchGraphs.
%
% David Martin <dmartin@eecs.berkeley.edu>
% May 2003

bsdsURL = 'http://www.cs.berkeley.edu/projects/vision/grouping/segbench/BSDS300';
presentations = {'gray','color'};
presNames = {'Grayscale','Color'};
iidsTest = imgList('test');

% Infer list of algorithms from directories present.
for k = 1:length(presentations),
  pres = presentations{k};
  dirlist = dir(fullfile(baseDir,pres));
  algs{k} = {};
  for i = 1:length(dirlist),
    alg = dirlist(i).name;
    if alg(1)=='.', continue; end
    if strcmp(alg,'human'), continue; end
    if ~isdir(fullfile(baseDir,pres,alg)), continue; end
    if length(dir(fullfile(baseDir,pres,alg,'name.txt')))~=1, continue; end
    if length(dir(fullfile(baseDir,pres,alg,'score.txt')))~=1, continue; end
    fname = fullfile(baseDir,pres,alg,'scores.txt');
    if length(dir(fname))~=1, continue; end
    tmp = dlmread(fname); % iid,thresh,r,p,f
    if size(tmp,1)~=numel(iidsTest), continue; end
    algs{k}{1+numel(algs{k})} = alg;
  end
end

% Read in all the scores.
for k = 1:length(presentations),
  pres = presentations{k};
  for i = 1:numel(algs{k}),
    alg = algs{k}{i};
    fprintf(2,'Processing directory %s/%s...\n',pres,alg);
    fname = fullfile(baseDir,pres,alg,'scores.txt');
    iscores{k}{i} = dlmread(fname); % iid,thresh,r,p,f
    fname = fullfile(baseDir,pres,alg,'score.txt');
    ascores{k}{i} = dlmread(fname); % thresh,r,p,f
    fname = fullfile(baseDir,pres,alg,'name.txt');
    fp = fopen(fname,'r');
    names{k}{i} = fgetl(fp);
    fclose(fp);
  end

  fname = fullfile(baseDir,pres,'human','scores.txt');
  if numel(dir(fname))>0,
    hiscores{k} = dlmread(fname); % iid,r,p,f
  else
    hiscores{k} = zeros(10000,4);
  end

  fname = fullfile(baseDir,pres,'human','score.txt');
  if numel(dir(fname))>0,
    hscore{k} = dlmread(fname); % r,p,f
  else
    hscore{k} = zeros(3,1);
  end
end

% Sort algorithms by overall F measure.
fprintf(2,'Sorting algorithms...\n');
for k = 1:length(presentations),
  pres = presentations{k};
  f = [];
  for i = 1:numel(algs{k}), f = [f ascores{k}{i}(4)]; end
  [unused,aperm{k}] = sort(f);
  aperm{k} = aperm{k}(end:-1:1);
end

% Create algorithms page.
fprintf(2,'Creating algorithms page...\n');
[u1,u2,u3] = mkdir(baseDir,'html');
mainPage = fullfile(baseDir,'html','algorithms.html');
fp = fopen(mainPage,'w');
title = 'Boundary Detection Benchmark: Algorithm Ranking';
fprintf(fp,'\n');
fprintf(fp,'\n');
fprintf(fp,'<title>%s</title>\n',title);
fprintf(fp,'\n');
fprintf(fp,'\n');
fprintf(fp,'
Go to Main Page.\n');
fprintf(fp,'
Go to Image Ranking.\n');
fprintf(fp,'
%s
\n',title);
fprintf(fp,'
Summary Tables
\n',presNames{k});
fprintf(fp,'

\n');
fprintf(fp,'
\n');
for k = 1:length(presentations),
  pres = presentations{k};
  fprintf(fp,'%s	\n',presNames{k});
end
fprintf(fp,'
\n');
fprintf(fp,'
\n');
for k = 1:length(presentations),
  fprintf(fp,'\n');
  pres = presentations{k};
  fprintf(fp,'

\n');
  fprintf(fp,'
Rank	Score	Algorithm
\n');
  fprintf(fp,'
\n');
  fprintf(fp,'0	\n');
  fprintf(fp,'%4.2f	\n',hscore{k}(3));
  fprintf(fp,'Humans	\n');
  fprintf(fp,'
\n');
  for i = 1:numel(algs{k}),
    alg = algs{k}{aperm{k}(i)};
    name = names{k}{aperm{k}(i)};
    score = ascores{k}{aperm{k}(i)}(4);
    fprintf(fp,'
\n');
    fprintf(fp,'%d	\n',i);
    fprintf(fp,'%4.2f	\n',score);
    fprintf(fp,'%s	\n',pres,alg,name);
    fprintf(fp,'
\n');
  end
  fprintf(fp,'
\n');
  fprintf(fp,'	\n');
end
fprintf(fp,'
\n');
fprintf(fp,'
\n');
fprintf(fp,'
Comparison Graphs
\n',presNames{k});
fprintf(fp,'

\n');
fprintf(fp,'
\n');
for k = 1:length(presentations),
  pres = presentations{k};
  fprintf(fp,'%s	\n',presNames{k});
end
fprintf(fp,'
\n');
fprintf(fp,'
\n');
for k = 1:length(presentations),
  fprintf(fp,'\n');
  fprintf(fp,'
\n');
  pres = presentations{k};
  for i = 1:numel(algs{k}),
    for j = i+1:numel(algs{k}),
      ii = aperm{k}(i);
      jj = aperm{k}(j);
      fprintf(fp,'
%s vs. %s\n',pres,i,j,names{k}{ii},names{k}{jj});
    end
  end
  fprintf(fp,'
\n');
  fprintf(fp,'	\n');
end
fprintf(fp,'
\n');
fprintf(fp,'
\n');
fprintf(fp,'
Detail Tables
\n',presNames{k});
for k = 1:length(presentations),
  pres = presentations{k};
  fprintf(fp,'
%s
\n',presNames{k});
  fprintf(fp,'

\n');
  fprintf(fp,'
Rank	Score	Algorithm	PR Curve
\n');
  fprintf(fp,'
\n');
  fprintf(fp,'0	\n');
  fprintf(fp,'%4.2f	\n',hscore{k}(3));
  fprintf(fp,'Humans	\n');
  fprintf(fp,'	\n',pres);
  fprintf(fp,'
\n');
  for i = 1:numel(algs{k}),
    alg = algs{k}{aperm{k}(i)};
    name = names{k}{aperm{k}(i)};
    score = ascores{k}{aperm{k}(i)}(4);
    fprintf(fp,'
\n');
    fprintf(fp,'%d	\n',i);
    fprintf(fp,'%4.2f	\n',score);
    fprintf(fp,'%s	\n',pres,alg,name);
    fprintf(fp,'	\n',pres,alg);
    fprintf(fp,'
\n');
  end
  fprintf(fp,'
\n');
end
fprintf(fp,'
Page generated on %s.\n',datestr(now));
fprintf(fp,'\n');
fprintf(fp,'\n');
fclose(fp);

% Create algorithm pages.
for k = 1:length(presentations),
  pres = presentations{k};
  for i = 1:numel(algs{k}),
    alg = algs{k}{i};
    fprintf(2,'Creating page for ''%s''...\n',alg);
    fname = fullfile(baseDir,pres,alg,'main.html');
    fp = fopen(fname,'w');
    title = sprintf('[%s] Boundary Detection Benchmark: Algorithm "%s"',presNames{k},names{k}{i});
    fprintf(fp,'\n');
    fprintf(fp,'\n');
    fprintf(fp,'<title>%s</title>\n',title);
    fprintf(fp,'\n');
    fprintf(fp,'\n');
    fprintf(fp,'
Back to Algorithm Ranking.\n');
    fprintf(fp,'
%s
\n',title);
    fname2 = fullfile(baseDir,pres,alg,'about.html');
    if length(dir(fname2))==1,
      fprintf(fp,'
\n');
      fp2 = fopen(fname2,'r');
      fwrite(fp,char(fread(fp2)'));
      fclose(fp2);
    end
    fprintf(fp,'
\n');
    fprintf(fp,'
Click on an image for additional details.\n');
    %fprintf(fp,'
Test Images
\n');
    fprintf(fp,'

\n');
    nper = 5;
    for j = 1:numel(iidsTest),
      iid = iidsTest(j);
      score = iscores{k}{i}(j,5);
      if iid~=iscores{k}{i}(j,1), error('bug'); end
      if mod(j,nper)==1, fprintf(fp,'
\n'); end
      fprintf(fp,'\n');
      fprintf(fp,'

\n');
      fprintf(fp,'#%d (%d) F=%4.2f
 ',j,iid,score);
      %fprintf(fp,'#%d (%d)
\n',j,iid);
      fprintf(fp,'\n',iid);
      fprintf(fp,'\n',bsdsURL,pres,iid);
      fprintf(fp,'\n');
      fprintf(fp,'

\n');
      fprintf(fp,'	\n');
      if mod(j,nper)==0 | j==numel(iidsTest), fprintf(fp,'
\n'); end
    end
    fprintf(fp,'
\n');
    fprintf(fp,'
Page generated on %s.\n',datestr(now));
    fprintf(fp,'\n');
    fprintf(fp,'\n');
    fclose(fp);
    % Create image pages for this algorithm.
    for j = 1:numel(iidsTest),
      iid = iidsTest(j);
      score = iscores{k}{i}(j,5);
      fname = fullfile(baseDir,pres,alg,sprintf('%d.html',iid));
      fp = fopen(fname,'w');
      title = sprintf(...
          '[%s] Boundary Detection Benchmark: Algorithm "%s" Image #%d (%d)',presNames{k},names{k}{i},j,iid);
      fprintf(fp,'\n');
      fprintf(fp,'\n');
      fprintf(fp,'<title>%s</title>\n',title);
      fprintf(fp,'\n');
      fprintf(fp,'\n');
      fprintf(fp,'
Back to Algorithm "%s" page.\n',names{k}{i});
      fprintf(fp,'
%s
\n',title);
      %fprintf(fp,'
F=%4.2f',score);
      fprintf(fp,'
\n',bsdsURL,pres,iid);
      fprintf(fp,'
\n');
      fprintf(fp,'
\n');
      fprintf(fp,'
Machine
	>\n',iid);
      fprintf(fp,'	\n',iid);
      fprintf(fp,'
\n');
      fprintf(fp,'
\n');
      fprintf(fp,'
Human
	>\n',iid);
      fprintf(fp,'	\n',iid);
      fprintf(fp,'
\n');
      fprintf(fp,'
\n');
      fprintf(fp,'
Page generated on %s.\n',datestr(now));
      fprintf(fp,'\n');
      fprintf(fp,'\n');
      fclose(fp);
    end
  end
end

% Sort the images by best F measure across all algorithms.
% Remember which algorithm had the best score for each image.
fprintf(2,'Sorting images...\n');
for k = 1:length(presentations),
  if numel(algs{k})==0, continue; end
  bestf{k} = zeros(numel(iidsTest),1);
  bestalg{k} = zeros(numel(iidsTest),1);
  for j = 1:numel(iidsTest),
    f = zeros(numel(algs{k}),1);
    for i = 1:numel(algs{k}), f(i) = iscores{k}{i}(j,5); end
    [bestf{k}(j),bestalg{k}(j)] = max(f);
  end
  [unused,iperm{k}] = sort(bestf{k});
  iperm{k} = iperm{k}(end:-1:1);
end

% Create images page.
fprintf(2,'Creating images page...\n');
mainPage = fullfile(baseDir,'html','images.html');
fp = fopen(mainPage,'w');
title = 'Boundary Detection Benchmark: Image Ranking';
fprintf(fp,'\n');
fprintf(fp,'\n');
fprintf(fp,'<title>%s</title>\n',title);
fprintf(fp,'\n');
fprintf(fp,'\n');
fprintf(fp,'
Go to Main Page.\n');
fprintf(fp,'
Go to Algorithm Ranking.\n');
fprintf(fp,'
%s
\n',title);
fprintf(fp,'
Click on an image for additional details.\n');
fprintf(fp,'

\n');
fprintf(fp,'
	\n');
for k = 1:length(presentations),
  fprintf(fp,'%s	\n',presNames{k});
end
fprintf(fp,'
\n');
fprintf(fp,'
Rank	\n');
for k = 1:length(presentations),
  fprintf(fp,'ID	Image	Best Algorithm [Score]	\n');
end
fprintf(fp,'
\n');

for j = 1:numel(iidsTest),
  fprintf(fp,'
\n');
  fprintf(fp,'%d	\n',j);
  for k = 1:length(presentations),
    if numel(algs{k})==0,
      fprintf(fp,'	\n');
      fprintf(fp,'	\n');
      fprintf(fp,'	\n');
      continue;
    end
    pres = presentations{k};
    iid = iidsTest(iperm{k}(j));
    f = bestf{k}(iperm{k}(j));
    maxf = hiscores{k}(iperm{k}(j),4);
    alg = algs{k}{bestalg{k}(iperm{k}(j))};
    name = names{k}{bestalg{k}(iperm{k}(j))};
    fprintf(fp,'#%d (%d)	\n',iperm{k}(j),iid);
    fprintf(fp,'\n');
    fprintf(fp,'\n',iid,pres);
    fprintf(fp,'\n',bsdsURL,pres,iid);
    fprintf(fp,'\n');
    fprintf(fp,'	\n');
    fprintf(fp,'%s
[ %4.2f / %4.2f ]	\n',pres,alg,name,f,maxf);
  end
  fprintf(fp,'
\n');
end
fprintf(fp,'
\n');
fprintf(fp,'
Page generated on %s.\n',datestr(now));
fprintf(fp,'\n');
fprintf(fp,'\n');
fclose(fp);

% Create image pages.
for j = 1:numel(iidsTest),
  iid = iidsTest(j);
  fprintf(2,'Creating pages for image #%d (%d)...\n',j,iid);
  for k = 1:length(presentations),
    if numel(algs{k})==0, continue; end
    pres = presentations{k};
    fname = fullfile(baseDir,'html',sprintf('%d-%s.html',iid,pres));
    fp = fopen(fname,'w');
    title = sprintf('[%s] Boundary Detection Benchmark: Image #%d (%d) Rank=%d',presNames{k},j,iid,find(iperm{k}==j));
    fprintf(fp,'\n');
    fprintf(fp,'\n');
    fprintf(fp,'<title>%s</title>\n',title);
    fprintf(fp,'\n');
    fprintf(fp,'\n');
    fprintf(fp,'
Back to Image Ranking.\n');
    fprintf(fp,'
Go to %s page.\n',iid,presentations{3-k},presNames{3-k});
    fprintf(fp,'
%s
\n',title);

    f = zeros(numel(algs{k}),1);
    for i = 1:numel(algs{k}), f(i) = iscores{k}{i}(j,5); end
    [unused,perm] = sort(f);
    perm = perm(end:-1:1);

    fprintf(fp,'

\n');
    fprintf(fp,'
Rank	Score	Algorithm	\n');
    fprintf(fp,'
\n');
    fprintf(fp,'0	\n');
    fprintf(fp,'%4.2f	\n',hiscores{k}(j,4));
    fprintf(fp,'Humans	\n');
    fprintf(fp,'
\n');
    for i = 1:numel(algs{k}),
      fprintf(fp,'
\n');
      fprintf(fp,'%d	\n',i);
      fprintf(fp,'%4.2f	\n',f(perm(i)));
      fprintf(fp,'%s	\n',names{k}{perm(i)});
      fprintf(fp,'
\n');
    end
    fprintf(fp,'
\n');

    fprintf(fp,'
\n');
    fprintf(fp,'\n',bsdsURL,pres,iid);
    fprintf(fp,'\n',pres,iid);

    fprintf(fp,'

\n');
    fprintf(fp,'
Rank Algorithm (Score)	Pb	Precision/Recall
\n');
    fprintf(fp,'
\n');
    fprintf(fp,'0
Humans
(%4.2f)	\n',hiscores{k}(j,4));
  fprintf(fp,'	\n',pres,iid);
  fprintf(fp,'	\n',pres,iid);
  fprintf(fp,'
\n');
    for i = 1:numel(algs{k}),
      fprintf(fp,'
\n');
      fprintf(fp,'%d
%s
(%4.2f)	\n',i,names{k}{perm(i)},f(perm(i)));
      fprintf(fp,'	\n',pres,algs{k}{perm(i)},iid);
      fprintf(fp,'	\n',pres,algs{k}{perm(i)},iid);
      fprintf(fp,'
\n');
    end
    fprintf(fp,'
\n');

    fprintf(fp,'
Page generated on %s.\n',datestr(now));
    fprintf(fp,'\n');
    fprintf(fp,'\n');
    fclose(fp);
  end
end


%% pdf_Sobol: Foo function for simulate a Sobol Set
%
% Usage:
%   pdf_Sobol()
%
% Inputs:
%     range            vector [min max] range of the random variable
%
% Output:
%     range            vector [min max] range of the random variable
% ------------------------------------------------------------------------
% See also
%
% Author : Flavio Cannavo'
% e-mail: flavio(dot)cannavo(at)gmail(dot)com
% Release: 1.0
% Date   : 01-02-2011
%
% History:
% 1.0  01-02-2011  First release.
%%

function range = pdf_Sobol(range)

range = range(:)';
% empty function


%test_PID
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

figure

colormap jet

s = 12;

PIDM = getPID(s, 1, planC, 'transverse', 'max');

subplot(1,3,1), imagesc(PIDM), axis image, title('transverse')

PIDM = getPID(s, 1, planC, 'saggital', 'max');

subplot(1,3,2), imagesc(PIDM), axis image, title('saggital')

PIDM = getPID(s, 1, planC, 'coronal', 'max');

subplot(1,3,3), imagesc(PIDM), axis image, colorbar, title('coronal')


function [X,A,row,col] = reshape_hsi(I,A)
%RESHAPE_HSI Summary of this function goes here
%   Detailed explanation goes here
if nargin < 2
    A = [];
end

if ndims(I) == 3
    [row,col,B] = size(I);
    N = row*col;
    if ~isempty(A)
        [row,col,M] = size(A);
        A = reshape(A, N, M);
    end
    X = reshape(I, N, B);
else
    [N,B] = size(I);
    row = N;
    col = 1;
    X = I;
end


function DEMO_niche_construction
% Demo of niche construction using active inference
%__________________________________________________________________________
%
% The free-energy principle is an attempt to explain the structure of the
% agent and its brain, starting from the fact that an agent exists (Friston
% and Stephan, 2007; Friston et al., 2010). More specifically, it can be
% regarded as a systematic attempt to understand the 'fit' between an
% embodied agent and its niche, where the quantity of free-energy is a
% measure for the 'misfit' or disattunement (Bruineberg and Rietveld, 2014)
% between agent and environment. This paper offers a proof-of-principle
% simulation of niche construction under the free-energy principle. The key
% point of this paper is that the minimum of free-energy is not at a point
% in which the agent is maximally adapted to the statistics of a static
% environment, but can better be conceptualized an attracting manifold
% within the joint  agent-environment state-space as a whole, which the
% system tends toward through mutual interaction. We will provide a general
% introduction to active inference and the free-energy principle. Using
% Markov Decision Processes (MDPs), we then describe a canonical generative
% model and the ensuing update equations that minimize free-energy. We then
% apply these equations to simulations of foraging in an environment; in
% which an agent learns the most efficient path to a pre-specified
% location. In some of those simulations, unbeknownst to the agent, the
% environment changes as a function of the activity of the agent (i.e.
% unintentional niche construction occurs). We will show how, depending on
% the relative inertia of the environment and agent, the joint
% agent-environment system moves to different attracting sets of jointly
% minimized free-energy.
%
% see also: spm_MPD_VB_X.m
%__________________________________________________________________________
% Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: DEMO_niche_construction.m 7679 2019-10-24 15:54:07Z spm $

%% Set up and preliminaries
%--------------------------------------------------------------------------
rng('default')

label.factor     = {'where'};
label.modality   = {'what','where'};
label.outcome{1} = {'open','closed'};
MAZE =  [...
    0 0 0 0 0 0 0 0;
    1 1 0 1 1 1 1 0;
    1 1 0 1 1 1 1 0;
    1 1 0 1 1 1 1 0;
    1 1 0 1 1 1 1 0;
    0 0 0 1 1 1 1 0;
    0 1 1 1 1 1 1 0;
    0 0 0 0 0 0 0 0];

END   = sub2ind(size(MAZE),1,1);                  % goal or target location
START = sub2ind(size(MAZE),8,1);

% prior beliefs about initial states: D
%--------------------------------------------------------------------------
D{1}  = zeros(numel(MAZE),1);
Ns    = numel(D{1});

% Capture generative process in form of A: Aaux
%--------------------------------------------------------------------------
Aaux{1} = [1 - MAZE(:), MAZE(:)]';                % what
Aaux{2} = eye(Ns,Ns);                             % where
Ng    = numel(Aaux);
for g = 1:Ng
    No(g)  = size(Aaux{g},1);
end

% controlled transitions: B (up, down, left, right, stay)
%--------------------------------------------------------------------------
u    = [1 0; -1 0; 0 1; 0 -1; 0 0];               % allowable actions
nu   = size(u,1);                                 % number of actions
B{1} = zeros(Ns,Ns,nu);
[n,m] = size(MAZE);
for i = 1:n
    for j = 1:m

        % allowable transitions from state s to state ss
        %------------------------------------------------------------------
        s     = sub2ind([n,m],i,j);
        for k = 1:nu
            try
                ss = sub2ind([n,m],i + u(k,1),j + u(k,2));
                B{1}(ss,s,k) = 1;
            catch
                B{1}(s, s,k) = 1;
            end
        end
    end
end

% priors: (negative cost) C:
%--------------------------------------------------------------------------
for g = 1:Ng
    C{g} = zeros(No(g),1);
end

% allowable policies (1 move): V
%--------------------------------------------------------------------------
V = 1:nu;

% basic MDP structure
%--------------------------------------------------------------------------
mdp.V = V;                      % allowable policies
mdp.B = B;                      % transition probabilities
mdp.C = C;                      % preferred outcomes
mdp.D = D;                      % prior over initial states

mdp.label = label;
mdp.alpha = 8;
mdp.tau   = 8;

%% Simulation 1: Learning over trials
%==========================================================================
% Define concentration parameters for environment:
%--------------------------------------------------------------------------
Acp.open   = [4;0];
Acp.closed = [0;4];

% Define concentration parameters for agent:
%--------------------------------------------------------------------------
acp     = [1/8;1/8];

% Generative process: Generate probabilistic mapping from hidden states to
% outcomes: A and matrix of concentration parameters
%--------------------------------------------------------------------------
[A, As] = spm_gen_process(Aaux, Acp);

% Generative model: Generate probabilistic mapping from hidden states to
% outcomes: a matrix
a{1} = repmat(acp, 1,size(A{1},2));
a{2} = A{2}*128;

% MDP structure
%--------------------------------------------------------------------------
mdp.A  = A;
mdp.As = As;
mdp.a  = a;
mdp    = spm_MDP_check(mdp);
ntime  = 16;    % number of moves per path
ntrial = 4;     % number of paths
mdpt   = mdp;

for i = 1:ntrial
    SDP  = spm_maze_active(mdpt,ntime,START,END);
    mdpt = SDP(end);
    trial(i).MDP = SDP;
end

% show results - behavioural
%--------------------------------------------------------------------------
spm_figure('GetWin','Figure 1'); clf
spm_print_agentstrials(trial, START, END, a)

%% Simulation 2: sensitivity to concentration parameters
%==========================================================================

% Show typical trial for
%--------------------------------------------------------------------------
acp    = [1/8,1/2,2;1/8,1/2,2];   % Initial concentration parameters of agent (cp1 = cp2)
ntime  = 16;                      % number of timesteps per trial
na     = length(acp);
ntrial = 4;
trial  = [];

for i = 1:na
    mdp.a{1} = repmat(acp(:,i), 1,size(A{1},2));
    mdpt = mdp;
    for j = 1:ntrial
        SDP = spm_maze_active(mdpt,ntime,START,END);
        mdpt = SDP(end);
    end
    trial(i).MDP = SDP;
end
spm_figure('GetWin','Figure 2'); clf
spm_plot_3a(trial, START, END, acp);

%% Simulation 3: sensitivity of concentration parameters agent and environment
%======================================================================
acp   = [1/8,4; 1/8,4];      % Initial concentration parameters of agent (cp1 = cp2)

Acp(1).open   = [1;0];
Acp(1).closed = [0;1];
Acp(2).open   = [16;0];
Acp(2).closed = [0;16];

ntime  = 16;                 % number of moves per path
ntrial = 32;                 % number of paths

% Inital concentration parameters
%--------------------------------------------------------------------------
na    = size(acp,2);
nenv  = size(Acp,2);
agent = [];

for i = 1:na
    mdp.a{1} = repmat(acp(:,i), 1,size(A{1},2));
    for j = 1:nenv
        [A,As] = spm_gen_process(Aaux, Acp(j));
        mdp.A  = A;
        mdp.As = As;
        mdpt   = mdp;
        for k = 1:ntrial
            SDP  = spm_maze_active(mdpt,ntime,START,END);
            mdpt = SDP(end);
            agent(i).env(j).trial(k).MDP = SDP;
        end
    end
end
spm_figure('GetWin','Figure 3'); clf
spm_plot_3b(agent, START, END);

%% Simulation 4: Singular value decomposition
%==========================================================================
spm_figure('GetWin','Figure 4'); clf
nenv  = 2;
ntt   = ntime*ntrial;
c     = linspace(10,ntt/4,ntt);
for i = 1:na
    for j = 1:nenv
        Pag  = [];
        Penv = [];
        for k = 1:ntrial
            SDP = agent(i).env(j).trial(k).MDP;
            for l = 1:ntime

                % get expectations
                %----------------------------------------------------------
                Pa   = SDP(l).a{1};
                Pa   = Pa/diag(sum(Pa));
                Pag  = [Pag, Pa(1,:)'];
                Pa   = SDP(l).As;
                Pa   = Pa/diag(sum(Pa));
                Penv = [Penv, Pa(1,:)'];
            end
        end
        Pag  = Pag  -  Pag(:,end)*ones(1,ntt);
        Penv = Penv - Penv(:,end)*ones(1,ntt);
        X    = [Pag'; Penv'];

        % eigenvariates
        %------------------------------------------------------------------
        subplot(2,2,2*(i-1) + j)
        [U,S] = svd(X);
        U   = U*S;
        V1a = U((1:ntt),1);
        V2a = U((1:ntt),2);
        V1e = U((1:ntt) + ntt,1);
        V2e = U((1:ntt) + ntt,2);

        scatter(V1a, V2a, [], c, 'filled'), hold on
        scatter(V1e, V2e, [], c, 'ro');
        axis([-1 1 -1 1]*2.5), axis square, hold off
        xlabel('First principle component')
        ylabel('Second principle component')
        title('phenotypic trajectories','FontSize',16)
    end
end

% get and show various free energies
%--------------------------------------------------------------------------
for i = 1:na
    for j = 1:nenv
        for k = 1:ntrial
            SDP = agent(i).env(j).trial(k).MDP;
            for l = 1:ntime;
                Gu     = log(spm_softmax(SDP(l).G));
                r(l,k) = mean(SDP(l).rt);
                f(l,k) = mean(SDP(l).H);
                g(l,k) = mean(SDP(l).P'*Gu);
            end
        end
        R(i,j,:) = sum(r);
        F(i,j,:) = sum(f);
        G(i,j,:) = sum(g);
    end
end

% plot
%--------------------------------------------------------------------------
spm_figure('GetWin','Figure 5'); clf
col = {'k','r';':k',':r'};

for i = 1:na
    for j = 1:nenv
        subplot(2,2,1)
        plot(spm_vec(F(i,j,:)),col{i,j}), hold on
        xlabel('exposure'), ylabel('seconds')
        title('(negative) free energy','FontSize',16)
        axis square, spm_axis tight, %set(gca,'YLim',[-3 1])

        subplot(2,2,2)
        plot(spm_vec(G(i,j,:)),col{i,j}), hold on
        xlabel('exposure'), ylabel('seconds')
        title('expected free energy','FontSize',16)
        axis square, spm_axis tight, %set(gca,'YLim',[-16 2])

        subplot(2,1,2)
        plot(spm_vec(R(i,j,:)),col{i,j}), hold on
        xlabel('exposure'), ylabel('seconds')
        title('reaction time','FontSize',16)
        axis square, spm_axis tight

    end
end

legend({'A:low-E:low','A:low-E:high','A:high-E:low','A:high-E:high'})

%%
return

function MDP = spm_maze_active(mdp,N,START,END)
% FORMAT MDP = spm_maze_search(mdp,N,START,END,alpha,beta,z)
% mdp   - MDP structure
% N     - number of moves (i.e., default 8)
% START - index of intial state (default 1)
% END   - index of target state (default 1)
% MDP   - MDP structure array

% preliminaries
%--------------------------------------------------------------------------
try, N;     catch, N     = 8;   end
try, START; catch, START = 1;   end
try, END;   catch, END   = 1;   end

% initialise concentration parameters: a (if unspecified)
%--------------------------------------------------------------------------
if ~isfield(mdp,'o')
    mdp.o = [];
end
if ~isfield(mdp,'u')
    mdp.u = [];
end
mdp.s    = START;

% Evaluate a sequence moves
%==========================================================================
for i = 1:N

    % Evaluate preferred states (subgoals) on the basis of current beliefs
    %----------------------------------------------------------------------
    mdp.C{2} = spm_maze_cost(mdp,END);

    % proceed with subsequent move
    %----------------------------------------------------------------------
    MDP(i)   = spm_MDP_VB_X(mdp);
    mdp      = MDP(i);
    mdp.s    = mdp.s(:,end);
    mdp.D{1} = MDP(i).X{1}(:,end);
    mdp.o    = [];
    mdp.u    = [];
    mdp.a{1} = MDP(i).a{1};

    % UPDATE: Change A matrix dependent on current position of agent
    %----------------------------------------------------------------------
    pos      = MDP(i).s(:,end);

    % Update environment
    %----------------------------------------------------------------------
    MDP(i).As(1,pos) = MDP(i).As(1,pos) + 1;

    % place in MDP structure
    %----------------------------------------------------------------------
    mdp.As   = MDP(i).As;
    mdp.A{1} = MDP(i).As/diag(sum(MDP(i).As));

end
return

function C = spm_maze_cost(MDP,END)
% Evaluate subgoals using
%==========================================================================
START = MDP.s(1);
if isfield(MDP,'a')
    Q = MDP.a{1};
else
    Q = MDP.A{1};
end
Q   = Q/diag(sum(Q));
Q   = Q(1,:);                                % open states
P   = diag(Q)*any(MDP.B{1},3);               % allowable transitions
ns  = length(Q);                             % number of states
X   = zeros(ns,1);X(START) = 1;              % initial state
Y   = zeros(ns,1);Y(END)   = 1;              % target state

% Preclude transitions to closed states and evaluate graph Laplacian
%--------------------------------------------------------------------------
P   = P - diag(diag(P));
P   = P - diag(sum(P));
P   = expm(P);

% evaluate (negative) cost as a path integral conjunctions
%--------------------------------------------------------------------------
for t = 1:size(MDP.V,1)
    X = P*X;
end
X     = X > exp(-3);                    % Default cut-off is -3
C     = log(X.*(P*Y) + exp(-32));

return

function spm_plot_3a (trial, START, GOAL, cp_ag)
% unpack properties
ntrial = size(trial,2);
ntime  = size(trial(1).MDP,2);
A  = spm_vec(trial(1).MDP(1).A{1}(1,:));
ns = numel(A);
ni = sqrt(ns);

for j = 1:ntrial

    A  = spm_vec(trial(j).MDP(end).A{1}(1,:));
    A  = reshape(A,ni,ni);
    subplot(2,ntrial,j), imagesc(A, [0,1]), axis image
    title(['CP = ' num2str(cp_ag(1,j))], 'fontsize',14)
    hold on, colormap gray

    % Plot trajectory
    %----------------------------------------------------------------------
    for k = 1:ntime
        step    = trial(j).MDP(k).s;
        [l1,m1] = ind2sub([ni,ni],step(1));
        [l2,m2] = ind2sub([ni,ni],step(2));
        plot([m1,m2], [l1,l2],':m');
    end

    [p,q] = ind2sub([ni,ni],START);
    plot(q,p,'.','MarkerSize',32,'Color','g');
    [p,q] = ind2sub([ni,ni],GOAL);
    plot(q,p,'.','MarkerSize',32,'Color','r');
    [p,q] = ind2sub([ni,ni],trial(j).MDP(end).s(2));
    plot(q,p,'.','MarkerSize',32,'Color','b');

    hold off

    % Plot Likelihood matrix
    %----------------------------------------------------------------------
    Q   = trial(j).MDP(end).a{1};
    Q   = Q/diag(sum(Q));
    Q   = Q(1,:);
    a   = reshape(Q(:),ni,ni);
    subplot(2,ntrial,j+3), imagesc(a, [0,1]), axis image
    title('Likelihood','fontsize',14);

end

return

function spm_plot_3b (agent, START, GOAL)

% unpack properties
%--------------------------------------------------------------------------
nag   = size(agent,2);
nenv  = size(agent(1).env,2);
ntime = size(agent(1).env(1).trial(1).MDP,2);
A     = spm_vec(agent(1).env(1).trial(1).MDP(1).A{1}(1,:));
ns    = numel(A);
ni    = sqrt(ns);

for i = 1:nenv
    for j = 1:nag
        A  = spm_vec(agent(j).env(i).trial(end).MDP(end).A{1}(1,:));
        A  = reshape(A,ni,ni);
        subplot(nenv,nag*2,(2*(j-1))+1+(2*nenv*(i-1)))
        imagesc(A, [0,1]), axis image

        hold on
        colormap gray
        % Plot trajectory
        %------------------------------------------------------------------
        for k = 1:ntime
            step    = agent(j).env(i).trial(end).MDP(k).s;
            [l1,m1] = ind2sub([ni,ni],step(1));
            [l2,m2] = ind2sub([ni,ni],step(2));
            plot([m1,m2], [l1,l2],':r');
        end

        [p,q] = ind2sub([ni,ni],START);
        plot(q,p,'.','MarkerSize',32,'Color','g');
        [p,q] = ind2sub([ni,ni],GOAL);
        plot(q,p,'.','MarkerSize',32,'Color','r');
        [p,q] = ind2sub([ni,ni],agent(j).env(i).trial(end).MDP(end).s(2));
        plot(q,p,'.','MarkerSize',32,'Color','b');

        % Plot Likelihood matrix
        %------------------------------------------------------------------
        Q   = agent(j).env(i).trial(end).MDP(end).a{1};
        Q   = Q/diag(sum(Q));
        Q   = Q(1,:);
        a   = reshape(Q(:),ni,ni);
        subplot(nenv,nag*2,(2*(j-1))+2+(2*nenv*(i-1))), imagesc(a, [0,1]), axis image

        hold off

    end
end
return

function [A, As] = spm_gen_process(Aaux, Acp)
% This function generates the observation matrix A of the generative
% process based on the layout of the maze Aaux and the environmental
% concentration parameters Acp
%--------------------------------------------------------------------------
initwh = Acp.open;
initbl = Acp.closed;
As     = initwh*Aaux{1}(1,:)+initbl*Aaux{1}(2,:);
Ap     = repmat(sum(As,1),2,1);

A{1} = As./Ap;    % Expected value of dirichlet is alpha1/(alpha1+alpha2);
A{2} = Aaux{2};

return

function spm_print_agentstrials(trial, START, GOAL,ainit)
%--------------------------------------------------------------------------
ntrial = size(trial,2);
ntime  = size(trial(1).MDP,2);
A  = spm_vec(trial(1).MDP(1).A{1}(1,:));
a  = ainit;
ns = numel(A);
ni = sqrt(ns);

% plot initial maze
%--------------------------------------------------------------------------
A  = spm_vec(trial(1).MDP(1).A{1}(1,:));
A  = reshape(A,ni,ni);
subplot(ntrial+1,2,1), imagesc(A, [0,1]), axis image
title('Initial maze', 'fontsize',14)
hold on
colormap gray
try
    [p,q] = ind2sub([ni,ni],START);
    plot(q,p,'.','MarkerSize',32,'Color','g');
    [p,q] = ind2sub([ni,ni],GOAL);
    plot(q,p,'.','MarkerSize',32,'Color','r');
end
hold off

% plot initial likelihood
%--------------------------------------------------------------------------
Q = a{1};
Q = Q/diag(sum(Q));
Q = Q(1,:);
a = reshape(Q(:),ni,ni);
subplot(ntrial+1,2,2), imagesc(a, [0,1]), axis image
title('Initial Likelihood','fontsize',14);

for j = 1:ntrial
    A = spm_vec(trial(j).MDP(end).A{1}(1,:));
    A = reshape(A,ni,ni);
    subplot(ntrial+1,2,1+(2*j)), imagesc(A, [0,1]), axis image
    title(['Trial ' num2str(j)], 'fontsize',14)
    hold on
    % Plot trajectory
    %----------------------------------------------------------------------
    for k = 1:ntime
        step = trial(j).MDP(k).s;
        [l1,m1]= ind2sub([ni,ni],step(1));
        [l2,m2]= ind2sub([ni,ni],step(2));
        p = plot([m1,m2], [l1,l2],':m');
    end

    % try
    %----------------------------------------------------------------------
    [p,q] = ind2sub([ni,ni],START);
    plot(q,p,'.','MarkerSize',32,'Color','g');
    [p,q] = ind2sub([ni,ni],GOAL);
    plot(q,p,'.','MarkerSize',32,'Color','r');
    [p,q] = ind2sub([ni,ni],trial(j).MDP(end).s(2));
    plot(q,p,'.','MarkerSize',32,'Color','b');

    hold off

    % Plot Likelihood matrix
    %----------------------------------------------------------------------
    Q     = trial(j).MDP(end).a{1};
    Q     = Q/diag(sum(Q));
    Q     = Q(1,:);
    a     = reshape(Q(:),ni,ni);
    subplot(ntrial+1,2,2+(2*j)), imagesc(a, [0,1]), axis image
    title(['Likelihood after trial ' num2str(j)],'fontsize',14);
end

return


function [tgraph,tedge,tloc]= createtimegraph(Graph,edge,loc,t)
%% Written by Muhammet Balcilar, France
% all rights reverved

nn=size(Graph,1);
tgraph=zeros(t*nn);
tedge=[];
tloc=loc;
eyeI=eye(nn);

for i=1:t-1
    tloc=[tloc;loc];
    tgraph((i-1)*nn+1:i*nn,i*nn+1:(i+1)*nn)=Graph+eyeI;
    tmp1=edge(:,1)+(i-1)*nn;
    tmp2=edge(:,2)+(i)*nn;
    tedge=[tedge; tmp1 tmp2];
    tmp=[1:nn]';
    tmp3=tmp+(i-1)*nn;
    tmp4=tmp+(i)*nn;
    tedge=[tedge; tmp3 tmp4];
end


function [sr_img_deconv, sr_img, sampled_img, sr_affix] = lmsSR_generateSRusingNUIv4weighted(lr_seq, warped_meshXN, warped_meshYN, upscaling, psf, lucy_iter, weighting_struct)
%
% LMSSR_GENERATESRUSINGNUIV4WEIGHTED Performs a Non-Uniform Interpolation (NUI) Super-Resolution (SR) approach with Spatial Quantization using Cubic Interpolation
%                                    and a Triple Sample Weighting. Supports GS/Y and YUV.
%    [sr_img_deconv, sr_img, sampled_img, sr_affix] = LMSSR_GENERATESRUSINGNUIV4WEIGHTED(lr_seq, warped_meshXN, warped_meshYN, upscaling, psf, lucy_iter, weighting_struct)
%
% Parameters: lr_seq             -   4-D matrix containing a LR YUV444 or GS/Y sequence (height,width,dye,frames)
%             warped_meshXN      -   Warped image mesh for X-coordinates
%             warped_meshYN      -   Warped image mesh for Y-coordinates
%             upscaling          -   1x2 vector containing the upscaling factors for Y- and X-coordinates
%             psf                -   Point spread function
%             lucy_iter          -   Number of iteration for the Lucy-Richardson deconvolution
%             weighting_struct   -   Struct containing the selected weighting mode + corresponding extra information:
%
%                mec_weight_flag   -   MEC Weighting ON/OFF (0: OFF. 1: ON, 2: ON [MECv2], 3: ON [MECv3], 4: ON [MECv4])
%                dis_weight_flag   -   Distance Weighting ON/OFF
%                qps_weight_flag   -   QP Weighting ON/OFF
%
%                mec_confMapN      -   3-D matrix containing confidence information in form of SSD values for each pixel and each auxiliary frame
%                mec_thr_scaler    -   Scalar value responsible for scaling the standard deviation threshold which cuts off SSD values that are too large [default: 2]
%                mec_weight_exp    -   Exponent for intensifying the weighting [default: 2]
%                mec_weighting     -   3-D matrix containing weights for each pixel depending on the quality of the MEC step
%
%                dis_rho           -   Distance Weighting Decay Factor [default: 0.7]
%                dis_scaler        -   Distance Weighting Scaling Factor [default: upscaling*10]
%                dis_weighting     -   3-D matrix containing weights for each pixel depending on the distance to the nearest pixel center
%
%                qps_map           -   3-D matrix containing the quantization parameters for each pixel and each frame including the reference frame
%                qps_rho           -   Quantization Weighting Decay Factor [default: 0.7]
%                qps_weighting     -   3-D matrix containing weights for each pixel depending on the quantization parameters
%
%                alpha             -   MEC Weighting Mixing Factor [default: 1]
%                beta              -   Distance Weighting Mixing Factor [default: 1]
%                gamma             -   Quantization Weighting Mixing Factor [default: 1]
%
% Author: Michel Bätz (LMS)
%
% See also: lmsSR_framework
%

sr_affix = 'sr2weighted000';

if weighting_struct.mec_weight_flag == 1,
    sr_affix(end-2) = '1';
elseif weighting_struct.mec_weight_flag == 2,
    sr_affix(end-2) = '2';
elseif weighting_struct.mec_weight_flag == 3,
    sr_affix(end-2) = '3';
elseif weighting_struct.mec_weight_flag == 4,
    sr_affix(end-2) = '4';
end

if weighting_struct.dis_weight_flag == 1,
    sr_affix(end-1) = '1';
elseif weighting_struct.dis_weight_flag == 2,
    sr_affix(end-1) = '2';
end

if weighting_struct.qps_weight_flag,
    sr_affix(end) = '1';
end

disp(['Weighting-Mode [',sr_affix(end-2:end),'] Selected..']);

alpha = weighting_struct.alpha;
beta  = weighting_struct.beta;
gamma = weighting_struct.gamma;

% Extract information from lr_seq
[lr_height,lr_width,dye,num_imgs] = size(lr_seq);

% Build Original X-Y-Position Grid
[lr_meshX,lr_meshY] = meshgrid(1:lr_width,1:lr_height);

% Build SR X-Y-Position Grid (+Padding)
[sr_meshX,sr_meshY] = meshgrid(1:lr_width*upscaling(2)+2*upscaling(2),1:lr_height*upscaling(1)+2*upscaling(1));

% Computing MEC weights from SSD values
if weighting_struct.mec_weight_flag == 1,
    weighting_struct.mec_weighting = lmsSR_computeWeightsMEC(weighting_struct.mec_confMapN,weighting_struct.mec_thr_scaler,weighting_struct.mec_weight_exp);
elseif weighting_struct.mec_weight_flag == 2,
    weighting_struct.mec_weighting = lmsSR_computeWeightsMECv2(weighting_struct.mec_confMapN,weighting_struct.mec_thr_scaler,weighting_struct.mec_weight_exp);
elseif weighting_struct.mec_weight_flag == 3,
    weighting_struct.mec_weighting = lmsSR_computeWeightsMECv3(weighting_struct.mec_confMapN,weighting_struct.mec_thr_scaler,weighting_struct.mec_weight_exp);
elseif weighting_struct.mec_weight_flag == 4,
    weighting_struct.mec_weighting = lmsSR_computeWeightsMECv4(weighting_struct.mec_confMapN,weighting_struct.mec_thr_scaler*10,weighting_struct.mec_weight_exp); % MAGI-ADD: Scaling with 10 necessary!
else
    weighting_struct.mec_weighting = ones(lr_height,lr_width,num_imgs);
end

% Computing QP weights from quantization parameters
if weighting_struct.qps_weight_flag, % MAGI-TODO: Work-in-Progress
    weighting_struct.qps_weighting = lmsSR_computeWeightsQP(weighting_struct.qps_map,weighting_struct.qps_rho);
else
    weighting_struct.qps_weighting = ones(lr_height,lr_width,num_imgs);
end

% Linearized Meshes (Direct Computation)
merged_meshX = zeros(lr_height,lr_width,num_imgs);
merged_meshY = zeros(lr_height,lr_width,num_imgs);

merged_meshX(:,:,1)     = lr_meshX;
merged_meshX(:,:,2:end) = warped_meshXN;

merged_meshY(:,:,1)     = lr_meshY;
merged_meshY(:,:,2:end) = warped_meshYN;

merged_lin_meshX = merged_meshX(~isnan(merged_meshX));
merged_lin_meshY = merged_meshY(~isnan(merged_meshY));

merged_valsY = lr_seq(:,:,1,:);
merged_lin_valsY = merged_valsY(~isnan(merged_meshX));
if dye == 3,
    merged_valsU = lr_seq(:,:,2,:);
    merged_valsV = lr_seq(:,:,3,:);
    merged_lin_valsU = merged_valsU(~isnan(merged_meshX));
    merged_lin_valsV = merged_valsV(~isnan(merged_meshX));
end

% Removing NaN-Positions of the QP/MEC Weighting Matrix and Linearizing It
merged_mec_weighting = weighting_struct.mec_weighting(~isnan(merged_meshX));
merged_qps_weighting = weighting_struct.qps_weighting(~isnan(merged_meshX));

num_pix = numel(merged_lin_meshX);

disp('... Throwing points into spatially quantized buckets ...');
%timeSR2bucket = tic;

% Averaging all samples inside the HR grid pixel patch
rounded_meshX = round(merged_lin_meshX*upscaling(2)) - upscaling(2) + 1;
rounded_meshY = round(merged_lin_meshY*upscaling(1)) - upscaling(1) + 1;

rounding_errX = abs(merged_lin_meshX - (rounded_meshX + upscaling(2) - 1)/upscaling(2));
rounding_errY = abs(merged_lin_meshY - (rounded_meshY + upscaling(1) - 1)/upscaling(1));

% Memory Cleansing
clear warped_meshXN warped_meshYN lr_seq lr_meshX lr_meshY merged_meshX merged_meshY merged_valsY merged_valsU merged_valsV merged_lin_meshX merged_lin_meshY mec_weighting

% Throwing away all mesh points that lie outside the SR image grid
outlier_vec = (rounded_meshX < 1) | (rounded_meshX > lr_width*upscaling(2)) | (rounded_meshY < 1) | (rounded_meshY > lr_height*upscaling(1));

rounded_meshX = rounded_meshX(~outlier_vec);
rounded_meshY = rounded_meshY(~outlier_vec);

rounding_errX = rounding_errX(~outlier_vec);
rounding_errY = rounding_errY(~outlier_vec);

% Distance Weighting Stuff
if weighting_struct.dis_weight_flag == 1,
    weighting_struct.dis_weighting = weighting_struct.dis_rho.^(sqrt((rounding_errY*weighting_struct.dis_scaler(1)).^2 + (rounding_errX*weighting_struct.dis_scaler(1)).^2));
elseif weighting_struct.dis_weight_flag == 2,
    weighting_struct.dis_weighting = weighting_struct.dis_rho.^(sqrt((rounding_errY*weighting_struct.dis_scaler(1)/2).^2 + (rounding_errX*weighting_struct.dis_scaler(1)/2).^2));
else
    weighting_struct.dis_weighting = ones(size(rounding_errX));
end

merged_lin_valsY = merged_lin_valsY(~outlier_vec);

tmp_sr_imgY = zeros(lr_height*upscaling(1),lr_width*upscaling(2)); % Creating bucketed image
if dye == 3,
    merged_lin_valsU = merged_lin_valsU(~outlier_vec);
    merged_lin_valsV = merged_lin_valsV(~outlier_vec);

    tmp_sr_imgU = zeros(lr_height*upscaling(1),lr_width*upscaling(2)); % Creating bucketed image
    tmp_sr_imgV = zeros(lr_height*upscaling(1),lr_width*upscaling(2)); % Creating bucketed image
end

merged_mec_weighting = merged_mec_weighting(~outlier_vec);
merged_qps_weighting = merged_qps_weighting(~outlier_vec);

counter_matrix = zeros(lr_height*upscaling(1),lr_width*upscaling(2)); % Matrix for counting the number of entries in each bucket
weighting_matrix = zeros(lr_height*upscaling(1),lr_width*upscaling(2)); % Matrix for the sum of MEC-DIS-QPS weights

num_pix = num_pix - sum(outlier_vec);

if dye == 3, % Color case
    for itera = 1:num_pix,
        % Weighted case
        tmp_sr_imgY(rounded_meshY(itera),rounded_meshX(itera))    = tmp_sr_imgY(rounded_meshY(itera),rounded_meshX(itera)) + merged_lin_valsY(itera)*alpha*merged_mec_weighting(itera)*beta*weighting_struct.dis_weighting(itera)*gamma*merged_qps_weighting(itera);
        tmp_sr_imgU(rounded_meshY(itera),rounded_meshX(itera))    = tmp_sr_imgU(rounded_meshY(itera),rounded_meshX(itera)) + merged_lin_valsU(itera)*alpha*merged_mec_weighting(itera)*beta*weighting_struct.dis_weighting(itera)*gamma*merged_qps_weighting(itera);
        tmp_sr_imgV(rounded_meshY(itera),rounded_meshX(itera))    = tmp_sr_imgV(rounded_meshY(itera),rounded_meshX(itera)) + merged_lin_valsV(itera)*alpha*merged_mec_weighting(itera)*beta*weighting_struct.dis_weighting(itera)*gamma*merged_qps_weighting(itera);

        counter_matrix(rounded_meshY(itera),rounded_meshX(itera))   = counter_matrix(rounded_meshY(itera),rounded_meshX(itera)) + 1;
        weighting_matrix(rounded_meshY(itera),rounded_meshX(itera)) = weighting_matrix(rounded_meshY(itera),rounded_meshX(itera)) + alpha*merged_mec_weighting(itera)*beta*weighting_struct.dis_weighting(itera)*gamma*merged_qps_weighting(itera);
    end

    % Weighted case
    tmp_sr_imgY = tmp_sr_imgY ./ weighting_matrix;
    tmp_sr_imgU = tmp_sr_imgU ./ weighting_matrix;
    tmp_sr_imgV = tmp_sr_imgV ./ weighting_matrix;
else % Grayscale case
    for itera = 1:num_pix,
        % Weighted case
        tmp_sr_imgY(rounded_meshY(itera),rounded_meshX(itera))    = tmp_sr_imgY(rounded_meshY(itera),rounded_meshX(itera)) + merged_lin_valsY(itera)*alpha*merged_mec_weighting(itera)*beta*weighting_struct.dis_weighting(itera)*gamma*merged_qps_weighting(itera);

        counter_matrix(rounded_meshY(itera),rounded_meshX(itera))   = counter_matrix(rounded_meshY(itera),rounded_meshX(itera)) + 1;
        weighting_matrix(rounded_meshY(itera),rounded_meshX(itera)) = weighting_matrix(rounded_meshY(itera),rounded_meshX(itera)) + alpha*merged_mec_weighting(itera)*beta*weighting_struct.dis_weighting(itera)*gamma*merged_qps_weighting(itera);
    end

    % Weighted case
    tmp_sr_imgY = tmp_sr_imgY ./ weighting_matrix;
end

disp('... Throwing points into spatially quantized buckets: Done.');
%toc(timeSR2bucket);

sampled_img = tmp_sr_imgY;
if dye == 3,
    sampled_img(:,:,2) = tmp_sr_imgU;
    sampled_img(:,:,3) = tmp_sr_imgV;
end

disp('... Interpolating data to the HR grid ...');
%timeSR2interp = tic;

% For Cubic Interpolation a slight Padding is required to avoid incorrectly interpolated values near the image borders
tmp_sr_imgY = padarray(tmp_sr_imgY,upscaling,'symmetric','both');
if dye == 3,
    tmp_sr_imgU = padarray(tmp_sr_imgU,upscaling,'symmetric','both');
    tmp_sr_imgV = padarray(tmp_sr_imgV,upscaling,'symmetric','both');
end

% Bringing the bucketed image into a linearized form for the griddata call
bucket_meshX = sr_meshX(~isnan(tmp_sr_imgY));
bucket_meshY = sr_meshY(~isnan(tmp_sr_imgY));

bucket_valsY  = tmp_sr_imgY(~isnan(tmp_sr_imgY));
if dye == 3,
    bucket_valsU  = tmp_sr_imgU(~isnan(tmp_sr_imgY));
    bucket_valsV  = tmp_sr_imgV(~isnan(tmp_sr_imgY));
end

% SR Reconstruction using Non-Uniform Interpolation (NUI)
% Griddata-Solution (ScatteredInterpolant is called from inside the griddata function)
tmp_Y = griddata(bucket_meshX,bucket_meshY,bucket_valsY,sr_meshX,sr_meshY,'cubic');%,'linear');
tmp_Y(isnan(tmp_Y)) = 0; % Temporary NaN treatment for Y
sr_img(:,:,1) = tmp_Y;
if dye == 3, % YUV444 Input
  tmp_U = griddata(bucket_meshX,bucket_meshY,bucket_valsU,sr_meshX,sr_meshY,'cubic');%,'linear');
  tmp_V = griddata(bucket_meshX,bucket_meshY,bucket_valsV,sr_meshX,sr_meshY,'cubic');%,'linear');
  tmp_U(isnan(tmp_U)) = 127/255; % Temporary NaN treatment for U
  tmp_V(isnan(tmp_V)) = 127/255; % Temporary NaN treatment for V
  sr_img(:,:,2) = tmp_U;
  sr_img(:,:,3) = tmp_V;
end
%sr_affix = [sr_affix,'lin'];

% Cropping the Padding
sr_img = sr_img(1+upscaling(1):end-upscaling(1),1+upscaling(2):end-upscaling(2),:);

disp('... Interpolating data to the HR grid: Done.');
%toc(timeSR2interp);

disp('... Deblurring SR image ...');
%timeSR2deblur = tic;

% Padding Image for the Deblurring Step
pad_size = 16; % This was 5 prior

sr_img_tmp = padarray(sr_img,[pad_size pad_size],'replicate','both');

% SR Deblurring Step (Deconvolution)
sr_img_deconv = deconvlucy(sr_img_tmp,psf,lucy_iter); % Lucy-Richardson deconvolution for deblurring (more iterations improves the result for checkerboard)

% Remove the Pading after the Deblurring Step
sr_img_deconv = sr_img_deconv(1+pad_size:end-pad_size,1+pad_size:end-pad_size,:);

disp('... Deblurring SR image: Done.');
%toc(timeSR2deblur);


function vw = spatialBlurTSeries(vw, scanList, kernelSize_mm, newTypeName)
% vw = spatialBlurTSeries(vw, scanList, kernelSize_mm, newTypeName)
%
% Performs spatial filtering on the time series data.
% Useful only in the inplane view.
%
% If 'dialog' is entered for the scanList argument, will pop up a dialog
% to get the parameters.
%
% Essentially an evil function that should be used only for fun. It's
% main use is for standardizing the sampling resolution across different
% sessions where the true voxel size changed for some reason.
%
% INPUTS:
% vw : mrVista view structure : default selectedInplane
% scanList : scans to filter : default all
% kernelSize_mm : FWHM of the kernel in mm : default 3mm. If a 3 element
% vector then sizes should be [x,y,z]: NOTE! Z (down the slices) is first
% newTypeName: default 'Blurred'
% ARW: 051804: Wrote it.
%
% Example:
%   spatialBlurTSeries(INPLANE{1},[1:2],3,'Blurred3mmAverages');
% .. then recompute the coranal in the new data type "Blurred3mmAverages"
%
% ras: 2005: added a dialog to get params. Don't think it's completely
% evil.

mrGlobals;

if (~exist('scanList','var') || isempty(scanList)), scanList = er_selectScans(vw); end
if (~exist('kernelSize_mm','var') || isempty(kernelSize_mm)), kernelSize_mm = 5; end
if (~exist('newTypeName','var') || isempty(newTypeName)), newTypeName='Blurred'; end

if isequal(lower(scanList), 'dialog')
    % pop up a dialog (or two)
    scanList = er_selectScans(vw, 'Select Scans to Spatially Blur');

    switch viewGet(vw, 'viewType')
        case 'Inplane'
            prompt={'Scan List:', 'Gaussian Kernel Size (mm):', ...
                'Name of New Data Type'};
            name='Input for Peaks function';
            defaults = {num2str(scanList), '3', 'Blurred3mm'};
        case 'Gray'
            prompt={'Scan List:', 'NumIterations Sigma:', ...
                'Name of New Data Type'};
            name='Input for Peaks function';
            defaults = {num2str(scanList), '9  0.5', 'dhkGraySmooth'};
    end
    resp = inputdlg(prompt,name, 1, defaults);
    scanList        = str2num(resp{1}); %#ok<*ST2NM>
    kernelSize_mm   = str2num(resp{2});
    newTypeName     = resp{3};
end

if ~existDataType(newTypeName), addDataType(newTypeName); end

origDataType=vw.curDataType;
srcDtName = dataTYPES(origDataType).name;

% if ~strcmp(vw.viewType,'Inplane')
%     error('This function only operates on inplane data');
% end

verbose = prefsVerboseCheck;

switch viewGet(vw, 'viewType')

    case 'Inplane'

        % Work out the size of the kernel we need in voxels
        % First find the effective voxel size:
        effectiveVoxSize_mm=mrSESSION.functionals(1).effectiveResolution(:);
        kernelSize_mm=kernelSize_mm(:);
        if (length(kernelSize_mm)~=3)
            kernelSize_mm=ones(3,1)*kernelSize_mm(1);
        end
        kernelRatio=kernelSize_mm./effectiveVoxSize_mm;
        support=kernelRatio*2;

        % Because we are going to have 'z' as the first dimension, rotate both
        % these vectors
        kernelRatio=kernelRatio([3 1 2]);
        support=support([3 1 2]);
        fprintf('\nKernel ratio=%d %d %d\n',kernelRatio(1),kernelRatio(2),kernelRatio(3));

        spatialFilter=gauss3d(support,kernelRatio);
        spatialFilter=spatialFilter./sum(spatialFilter(:));

        hiddenView = initHiddenInplane;

        % Pre-define a large matrix to hold all the data for a single scan
        % This will be nVoxels*nVoxels*nSlices*nTRs
        scanParams= dataTYPES(origDataType).scanParams(1);
        nx=scanParams.cropSize(1);
        ny=scanParams.cropSize(2);
        nSlices=length(scanParams.slices);

    case 'Gray'
        hiddenView = initHiddenGray;
end

hiddenView = selectDataType(hiddenView,existDataType(newTypeName));

for thisScan=1:length(scanList)

    % Initialize the new scan in dataTYPES.
    newScanNum = viewGet(hiddenView, 'num scans')+1;
    initScan(vw, newTypeName, newScanNum, {srcDtName scanList(thisScan)});

    switch viewGet(vw, 'viewType')
        case 'Inplane'
            nTR = viewGet(vw, 'NumFrames', scanList(thisScan));
            if verbose, disp('Allocating large matrix'); end
            dataArray=zeros(nTR,nx,ny,nSlices);

            % Get the tSeries directory for this dataType
            % (make the directory if it doesn't already exist).
            tseriesdir = tSeriesDir(hiddenView);

            % Make the Scan subdirectory for the new tSeries (if it doesn't exist)
            scandir = fullfile(tseriesdir,['Scan',num2str(newScanNum)]);
            if ~exist(scandir,'dir')
                mkdir(tseriesdir,['Scan',num2str(newScanNum)]);
            end

            % Load in the full data set for each scan
            % (nVoxelsx*nVoxelsy*nSlices*nTR)
            % Then loop through the TRs performing a spatial blur (convn) on the volume
            % at each time point.
            disp('Loading');
            for thisSlice=1:nSlices
                thisSliceData=loadtSeries(vw,scanList(thisScan),thisSlice); % Data come in as nTR*nVoxels
                dataArray(:,:,:,thisSlice)=reshape(thisSliceData,nTR,nx,ny);
            end

            % Now loop over TRs doing the convolution
            disp('Convolving');
            for thisTR=1:nTR
                dataArray(thisTR,:,:,:)=convn(dataArray(thisTR,:,:,:),spatialFilter,'same');
            end

            % Now loop over slices again, saving out the data
            disp('Saving');

            dataArray = permute(dataArray, [1 2 4 3]);

            savetSeries(dataArray,hiddenView,thisScan);

        case 'Gray'
            tSeries = loadtSeries(vw,scanList(thisScan));
            iterlambda = kernelSize_mm;
            tSeries = dhkGraySmooth(vw,tSeries,iterlambda);
            %This should be fine since we this is a 'gray' view
            savetSeries(tSeries, hiddenView,thisScan,1);
    end

    fprintf('\nDone scan %d\n',thisScan);

end % next scan

% Loop through the open views, switch their curDataType appropriately,
% and update the dataType popups
INPLANE = resetDataTypes(INPLANE);
VOLUME  = resetDataTypes(VOLUME);
FLAT    = resetDataTypes(FLAT);

% in the provided view, select the new data type
vw = selectDataType(vw, newTypeName);

return;


% This file load eq catalogs in hypoellipes format. Since the formated readin-
% is fast, this is the best way to load data for
% large catalogs.
% Earthquakes within a rectengular box (latmin latmax lonmin lonmax)
% a time window and a magnitude threshold can be selected.
% Note: lat/Lon are assumed to be in minutes in the original catalog
%
% last modified: March 96   stefan wiemer

report_this_filefun(mfilename('fullpath'));

%  close the file in case it is still open
safe_fclose(fid);

% selection criteria
tmin = 1960.0001;
tmax = 2005;
lonmin = -180.0;
lonmax =  180.0;
latmin = -90.0;
latmax = 90.0 ;
Mmin = 0.0
deperr = 1000.5;

a = []; b = [];
n2 = 0;

% open the file and read 2000 lines at a time
[file1,path1] = uigetfile([ '*.sum'],' Earthquake Datafile');
fid = fopen([path1 file1],'r') ;;

while  ferror(fid) == ''
    %  l =fscanf(fid,'%2d%2d%2d%2d%2d%4d%2d%*1c%4d%3d%*1c%4d%5f%2d%*31c%2d%*15c%4d',[14 2000]) ;
    % variabl #   1  2  3  4  5  6  7     8  9      10 11 12    13    14
    % position    2  4  6  8 10 14 16  17 21 24 25  29 34 36 45  49 54  58
    %  l =fscanf(fid,'%2d%2d%2d%2d%2d%4d%2d%*1c%4d%3d%*1c%4d%5f%2d%*9c%4d%*5c%4d',[14 2000]) ;
    %            yr mo da hr mi
    % variabl #   1  2  3  4  5     6  7     8   9     10 11      12     13 14     15
    % position    2  4  6  8 10 11 17  20 21 26 30  31 36 43   81 84  85 87 91  93 97
    l =fscanf(fid,'%4d%2d%2d%2d%2d%*1c%6d%3d%*1c%5d%4d%*1c%5d%7d%*38%3d%*1c%2d%4d%*2c%4d',[15   2000]);

    n2 = n2 +  length(l(1,:));

    % make the catalog in the correct format
    % lon lat yr mo da mag dep hr min dip_direction dip rake misfit
    b = [ -l(9,:)-l(10,:)/6000 ; l(7,:)+l(8,:)/6000 ;...
        l(1,:);l(2,:);l(3,:);l(12,:)/10;l(11,:)/100;l(4,:);...
        l(5,:);l(13,:); l(14,:);l(15,:);l(16,:);l(17,:);l(18,:)];
    b = b';
    % l =  b(:,6) >= Mmin & b(:,1) >= lonmin & b(:,1) <= lonmax & ...
    % b(:,2) >= latmin & b(:,2) <= latmax & b(:,3) <= tmax  & ...
    % b(:,3) >= tmin & b(:,10) <= deperr;
    a = [a ; b];
    disp([ num2str(n2,10) ' earthquakes scanned, ' num2str(length(a)) ' EQ found'])
    %  if max(b(:,3)) >  tmax ; break; end
end
ferror(fid)
fclose(fid);
dep1 = 0.3*(max(a.Depth)-min(a.Depth))+min(a.Depth);
dep2 = 0.6*(max(a.Depth)-min(a.Depth))+min(a.Depth);
dep3 = max(a.Depth);

stri1 = [file1];
tim1 = minti;
tim2 = maxti;
minma2 = minma;
maxma2 = maxma;
minde = min(a.Depth);
maxde = max(a.Depth);
rad = 50.;
ic = 0;
ya0 = 0.;
xa0 = 0.;
iwl3 = 1.;
step = 3;
t1p(1) = 80.;
t2p(1) = 85.;
t3p(1) = 90.;
t4p(1) = 93.;
tresh = 10;

% save the catalog
save newcat.mat a


function [RUMBA_outputs, UpRegulated, DownRegulated, MetConnectivity1, MetConnectivity2] = rumba(model1, model2, completeModel, sampling, maxMetConn, RxnsOfInterest, GenesOfInterest, NormalizePointsOption, PValCuttoff, MaxNumPoints, LoopRxnsToIgnore, verboseTag)
% RUMBA predicts which reactions significantly change their
% flux at metabolic branch points under two conditions
%
% USAGE:
%
%    [RUMBA_outputs, UpRegulated, DownRegulated, MetConnectivity1, MetConnectivity2] = rumba(model1, model2, completeModel)
% INPUTS:
%    model1:                     Model under first condition, exchange reactions
%                                are constrained with the data related to the first
%                                condition. If model already sampled
%                                ('sampling' = 0). The sampling points is in an
%                                mxn matrix with m reactions and n points included
%                                as a field in the model(i.e., `model1.points`).
%                                Set 'sampling' = 1 to set the model constrained
%                                under the first conditions
%    model2:                     Model under second condition. Same
%                                format as `model1`.
%    completeModel:              The complete reference model. This is used
%                                to verify consistency between the sampled models.
%
% OPTIONAL INPUTS:
%    sampling:                   0, if no sampling needed (default)
%                                1, if sampling of the models under both
%                                conditions
%    maxMetConn:                 The maximum connectivity of a metabolite to
%                                consider. All branch points with a higher
%                                connectivity will be ignored (default = 30)
%    RxnsOfInterest:             Reactions for which predictions are desired.
%                                Specifying only desired reactions speeds up
%                                algorithm (default = all reactions)
%    GenesOfInterest:            Genes associated with the reactions of interest (default = all genes)
%    NormalizePointsOption:      Option to normalize sample points to (1) the
%                                same median of magnitude of flux through all
%                                non-loop gene-associated reactions, or (2) the
%                                optimal growth rate. (default = 1)
%    PValCuttoff:                P-value cutoff used to decide which changes in
%                                branch point flux to call significant (two-
%                                tailed p-value, so .05 will mean 0.25 on both
%                                tails). (default = 0.05)
%    MaxNumPoints:               Maximum number of points to use form the
%                                sampled models. Extra points will be removed
%                                to improve memory usage and speed up
%                                calculations. (default = minimum number of
%                                points in the model or 500 points, whichever
%                                is smaller)
%    verboseTag:                 1 = print out progress and use waitbars (default).
%			 	 0 = print only minimal progress to screen.
%    LoopRxnsToIgnore:           list of rxns associated with loop within the model,
%                                (default - reaction loops defined using FVA)
%
% OUTPUTS:
%    RUMBA_outputs:              Structure containing all information about
%                                each gene-reaction pair. For gene-reaction pair
%                                for which the differential branch-point
%                                information is possible to calculate: the list of
%                                connected metabolites ('ConnectedMets'), the associated
%                                up-regulation p-value ('pValue_up'), the associated
%                                down-regulation p-value ('pValue_down')and
%                                the reaction directionality for both model
%                                ('direction').The structure also contains the list of gene-reaction
%                                pairs for which no differential branch-point
%                                information can be determined (because of
%                                loops, unused pathways, etc.).
%    UpRegulated:                first column : Gene-reaction pairs towards which flux is
%                                significantly upregulated during the shift;
%                                second column : list of metabolites
%                                connected to the gene-reaction pair;
%                                third column : Magnitude of absolutes flux change
%    DownRegulated:              same structure as `UpRegulated` but for gene-reaction pairs
%                                from which flux is significantly
%                                downregulated during the shift
%    MetConnectivity1:           A structure that present for each metabolite present in model1
%                                the following sets of fields:
%
%                                  * ConnRxns - the reactions that are connected
%                                    to the metabolite
%                                  * Sij - The stoichiometric coefficient for the
%                                    metabolite in each reaction in ConnRxns
%                                  * RxnScore - Score for each reaction in ConnRxns
%                                  * Direction - The direction of reaction flux
%                                    for each sample point
%                                  * MetNotUsed - Whether or not the metabolite is
%                                    used in the condition
%    MetConnectivity2:           Same as `MetConnectivity1` but for `model2`
%
%
% .. Authors:
%       - Nathan E. Lewis, May 2010-May 2011
%       - Anne Richelle, May 2017

if nargin < 12  || isempty(verboseTag) % Set the function to not use waitbars and lots of status text.
    verboseTag = 0;
end
if nargin < 11  || isempty(LoopRxnsToIgnore)
    tmp = completeModel;
    tmpExc = findExcRxns(tmp);
    tmp.lb(tmpExc) = 0;
    tmp.lb(tmp.lb >0) = 0;
    tmp.ub(tmpExc) = 0;
    [MinFVA MaxFVA] = fluxVariability(tmp,0,'max',tmp.rxns);
    LoopRxnsToIgnore = tmp.rxns(or(MinFVA<-1e-10, MaxFVA>1e-10));
    LoopRxnsToIgnore = {};
    tmpRxnForm = printRxnFormula(tmp,LoopRxnsToIgnore);
end

% Set the minimum p-value cutoff to 0.05 for determining significant shifts at metabolites
if nargin <9 || isempty(PValCuttoff)
    PValCuttoff = 0.05;
end

% Default is to normalize the points between the two models by net flux
if nargin < 8  || isempty(NormalizePointsOption)
    NormalizePointsOption = 1;
end

% If no set of genes is provided, look at all genes
if nargin <6
    [tmp_r,tmp_r2] = findRxnsFromGenes(completeModel, completeModel.genes, 0, 1);
    RxnsOfInterest = tmp_r2(:,1);
    GenesOfInterest = tmp_r2(:,5);
end

% if no metabolite connectivity filter is provided, filter out all
% metabolite with a connectivity greater than 30
if nargin < 5 || isempty(maxMetConn)
    maxMetConn = 30;
end

% if no sampling option, models are already sampled
if nargin < 4 || isempty(sampling)
    sampling = 0;
    if ~isfield(model1,'points'),
        warning 'Model1 is not sampled, sampling will be performed using sampleCbModel'
        sampling = 1;
    end
    if ~isfield(model2,'points'),
        warning 'Model2 is not sampled, sampling will be performed using sampleCbModel'
        sampling = 1;
    end
end

if sampling == 1
    %Sampling of the model 1
    [model1Sampling,samples1] = sampleCbModel(model1, 'model1Sampling');
    model1=model1Sampling;
    model1.points=samples1;
    %Sampling of the model 2
    [model2Sampling,samples2] = sampleCbModel(model2, 'model2Sampling');
    model2=model2Sampling;
    model2.points=samples2;
end

% Set the maximum number of points to look at to 500 or the minimum number of points in the model
if nargin < 10 || isempty(MaxNumPoints)
    MaxNumPoints = min([500;length(model1.points(1,:)); length(model2.points(1,:))]);
end

% since the statistics should be two-tailed, divide the p-value by 2
PValCuttoff = PValCuttoff/2;

% preprocessing step: Make sure all reactions from complete model are
% are in the sampled models
model1 = addMissingReactions(model1, completeModel);
model2 = addMissingReactions(model2, completeModel);

% Normalize the sampled points by scaling by the net network flux (1 = by
% net flux, 2 = by growth rate
    [model1,model2] = normalizePoints(model1, model2, NormalizePointsOption, LoopRxnsToIgnore);

% Rename genes to avoid incompatibilities
model1.genes = regexprep(model1.genes,'[_\-]','');% remove underscores and hyphens
model2.genes = regexprep(model2.genes,'[_\-]','');
completeModel.genes = regexprep(completeModel.genes,'[_\-]','');
GenesOfInterest = regexprep(GenesOfInterest,'[_\-]','');

% check to make sure there is enough sample points
if MaxNumPoints > min([length(model1.points(1,:)); length(model2.points(1,:))])
    MaxNumPoints = min([length(model1.points(1,:)); length(model2.points(1,:))]);
    warning('Number of sample points desired is more than available number in models!')
    display(cat(2,'you need to use ',num2str(MaxNumPoints),' points.'))
end

% for each metabolite get all incoming and outgoing reaction and score them
display('Processing first condition.')
[MetConnectivity1, ConnectedMet1] = classifyRxns(completeModel, model1, maxMetConn, MaxNumPoints, verboseTag, LoopRxnsToIgnore);
display('Processing second condition.')
[MetConnectivity2, ConnectedMet2] = classifyRxns(completeModel, model2, maxMetConn, MaxNumPoints, verboseTag, LoopRxnsToIgnore);
display('Comparing conditions.')
[MetsAndRxns,pVal_up,pVal_down,Dir_model1,Dir_model2] = compareConditions(MetConnectivity1, ConnectedMet1, MetConnectivity2, ConnectedMet2);

% process the 'compareCondtions' results
RUMBA_Struc_Pred = struct;
RUMBA_Struc_noPred = struct;
UpRegulated = {};
DownRegulated = {};
UpRegulated_mets = {};
DownRegulated_mets = {};
RUMBA_outputs=struct;
noPred={}

display('Classifying reaction/gene pair changes')
% step through all reactions of interest and determine if they
% significantly change
for i=1:length(RxnsOfInterest)
    % find whether split flux is increasing or decreasing for each reaction
    Ind = find(ismember(MetsAndRxns(:,2),RxnsOfInterest{i}));
    if ~isempty(Ind)

        Pred.ConnectedMets = regexprep(MetsAndRxns(Ind,1),'Met_',''); % metabolites to which the reaction is connected
        Pred.pValue_up = pVal_up(Ind); % p-value that flux is diverted to this reaction in each node in which it participates
        Pred.pValue_down = pVal_down(Ind); % p-value that flux is diverted away from this reaction in each node in which it participates
        Pred.Direction = [Dir_model1(Ind) Dir_model2(Ind)]'; % reaction directionality for both model (1 producing metabolite, -1 consuming the metabolite)

        RUMBA_outputs.(cat(2,GenesOfInterest{i},'_',RxnsOfInterest{i}))=Pred;

        % if the rxn/gene pair goes up for at least one metabolite, but not
        % down, and is above the p-value cutoff, then put it in the list of
        % gene-reaction pairs that significantly go up
        if min(pVal_up(Ind))<PValCuttoff && max(pVal_up(Ind))<=(1-PValCuttoff)
            UpRegulated{end+1} = cat(2,GenesOfInterest{i},'_',RxnsOfInterest{i});
            UpRegulated_mets{end+1} = regexprep(MetsAndRxns(Ind(pVal_up(Ind)<PValCuttoff),1),'Metab_','');
        end

        % if the rxn/gene pair goes down for at least one metabolite, but
        % not up  and is above the p-value cutoff, then put it in the list
        % of gene-reaction pairs that significantly go down
        if min(pVal_down(Ind))<PValCuttoff && max(pVal_down(Ind))<=(1-PValCuttoff)
            DownRegulated{end+1} = cat(2,GenesOfInterest{i},'_',RxnsOfInterest{i});
            DownRegulated_mets{end+1} = regexprep(MetsAndRxns(Ind(pVal_down(Ind)<PValCuttoff),1),'Metab_','');
        end

    else
        noPred{end+1}=([GenesOfInterest{i},'_',RxnsOfInterest{i}]);
    end
end
RUMBA_outputs.NotPredicted=noPred;

[UpRegulated,Ind] = sort(UpRegulated');
UpRegulated_mets = UpRegulated_mets(Ind)';
[DownRegulated,Ind] = sort(DownRegulated');
DownRegulated_mets = DownRegulated_mets(Ind)';

%filter out genes that go up and down
tmpUp = regexprep(UpRegulated,'_[0-9A-Za-z\-_\.\,\''\"\(\)\[\]]+$','');    % get all up gene IDs
tmpDwn = regexprep(DownRegulated,'_[0-9A-Za-z\-_\.\,\''\"\(\)\[\]]+$',''); % get all down gene IDs
ToDelU = ismember(tmpUp,tmpDwn);                                           % find Up genes also in the Down category
ToDelD = ismember(tmpDwn,tmpUp);                                           % find Down genes also in the Up category

UpRegulated(ToDelU)=[];
DownRegulated(ToDelD)=[];
UpRegulated_mets(ToDelU)=[];
DownRegulated_mets(ToDelD)=[];

UpRegulated = ([UpRegulated UpRegulated_mets]);
DownRegulated = ([DownRegulated DownRegulated_mets]);

% rank each reaction by the median magnitude change
[rxnsInCommon,MedRxnChange] = pValDistForModelOverlap(model1,model2);
tmpUp = regexprep(UpRegulated(:,1),'^[0-9A-Za-z\-\.\,\''\"\(\)\[\]]+_','');
tmpDwn = regexprep(DownRegulated(:,1),'^[0-9A-Za-z\-\.\,\''\"\(\)\[\]]+_','');

MagnitudeUp = zeros(length(tmpUp),1);
for i = 1:length(tmpUp)
	Ind = find(ismember(rxnsInCommon,tmpUp{i}));
	if isempty(Ind)
    	display(cat(2,'Reaction: ',tmpUp{i},' is missing!'))
    elseif length(Ind)>1
    	display(cat(2,'Reaction: ',tmpUp{i},' is duplicated in model!'))
    else
    	MagnitudeUp(i) = abs(MedRxnChange(Ind));
    end
end

MagnitudeDown = zeros(length(tmpDwn),1);
for i = 1:length(tmpDwn)
	Ind = find(ismember(rxnsInCommon,tmpDwn{i}));
	if isempty(Ind)
    	display(cat(2,'Reaction: ',tmpDwn{i},' is missing!'))
    elseif length(Ind)>1
        display(cat(2,'Reaction: ',tmpDwn{i},' is duplicated in model!'))
    else
    	MagnitudeDown(i) = abs(MedRxnChange(Ind));
    end
end

UpRegulated = ([UpRegulated num2cell(MagnitudeUp)]);
DownRegulated = ([DownRegulated num2cell(MagnitudeDown)]);

end


function Offspring = OperatorGAhalf(Problem,Parent,Parameter)
%OperatorGAhalf - Crossover and mutation operators of genetic algorithm.
%
%   This function is the same to OperatorGA, while only the first half of
%   the offsprings are evaluated and returned.
%
%   See also OperatorGA

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

    if nargin > 2
        [proC,disC,proM,disM] = deal(Parameter{:});
    else
        [proC,disC,proM,disM] = deal(1,20,1,20);
    end
    if isa(Parent(1),'SOLUTION')
        evaluated = true;
        Parent    = Parent.decs;
    else
        evaluated = false;
    end
    Parent1   = Parent(1:floor(end/2),:);
    Parent2   = Parent(floor(end/2)+1:floor(end/2)*2,:);
    Offspring = zeros(size(Parent1,1),size(Parent1,2));
    Type      = arrayfun(@(i)find(Problem.encoding==i),1:5,'UniformOutput',false);
    if ~isempty([Type{1:2}])    % Real and integer variables
        Offspring(:,[Type{1:2}]) = GAreal(Parent1(:,[Type{1:2}]),Parent2(:,[Type{1:2}]),Problem.lower([Type{1:2}]),Problem.upper([Type{1:2}]),proC,disC,proM,disM);
    end
    if ~isempty(Type{3})        % Label variables
        Offspring(:,Type{3}) = GAlabel(Parent1(:,Type{3}),Parent2(:,Type{3}),proC,proM);
    end
    if ~isempty(Type{4})        % Binary variables
        Offspring(:,Type{4}) = GAbinary(Parent1(:,Type{4}),Parent2(:,Type{4}),proC,proM);
    end
    if ~isempty(Type{5})        % Permutation variables
        Offspring(:,Type{5}) = GApermutation(Parent1(:,Type{5}),Parent2(:,Type{5}),proC);
    end
    if evaluated
        Offspring = Problem.Evaluation(Offspring);
    end
end

function Offspring = GAreal(Parent1,Parent2,lower,upper,proC,disC,proM,disM)
% Genetic operators for real and integer variables

    %% Simulated binary crossover
    [N,D] = size(Parent1);
    beta  = zeros(N,D);
    mu    = rand(N,D);
    beta(mu<=0.5) = (2*mu(mu<=0.5)).^(1/(disC+1));
    beta(mu>0.5)  = (2-2*mu(mu>0.5)).^(-1/(disC+1));
    beta = beta.*(-1).^randi([0,1],N,D);
    beta(rand(N,D)<0.5) = 1;
    beta(repmat(rand(N,1)>proC,1,D)) = 1;
    Offspring = (Parent1+Parent2)/2+beta.*(Parent1-Parent2)/2;

    %% Polynomial mutation
    Lower = repmat(lower,N,1);
    Upper = repmat(upper,N,1);
    Site  = rand(N,D) < proM/D;
    mu    = rand(N,D);
    temp  = Site & mu<=0.5;
    Offspring       = min(max(Offspring,Lower),Upper);
    Offspring(temp) = Offspring(temp)+(Upper(temp)-Lower(temp)).*((2.*mu(temp)+(1-2.*mu(temp)).*...
                      (1-(Offspring(temp)-Lower(temp))./(Upper(temp)-Lower(temp))).^(disM+1)).^(1/(disM+1))-1);
    temp = Site & mu>0.5;
    Offspring(temp) = Offspring(temp)+(Upper(temp)-Lower(temp)).*(1-(2.*(1-mu(temp))+2.*(mu(temp)-0.5).*...
                      (1-(Upper(temp)-Offspring(temp))./(Upper(temp)-Lower(temp))).^(disM+1)).^(1/(disM+1)));
end

function Offspring = GAlabel(Parent1,Parent2,proC,proM)
% Genetic operators for label variables

    %% Uniform crossover
    [N,D] = size(Parent1);
    k     = rand(N,D) < 0.5;
    k(repmat(rand(N,1)>proC,1,D)) = false;
    Offspring    = Parent1;
    Offspring(k) = Parent2(k);

    %% Bitwise mutation
    Site = rand(N,D) < proM/D;
    Rand = randi(D,N,D);
    Offspring(Site) = Rand(Site);

    %% Repair
    for i = 1 : N
        Off = zeros(1,D);
        while ~all(Off)
            x = find(~Off,1);
            Off(Offspring(i,:)==Offspring(i,x)) = max(Off) + 1;
        end
        Offspring(i,:) = Off;
    end
end

function Offspring = GAbinary(Parent1,Parent2,proC,proM)
% Genetic operators for binary variables

    %% Uniform crossover
    [N,D] = size(Parent1);
    k     = rand(N,D) < 0.5;
    k(repmat(rand(N,1)>proC,1,D)) = false;
    Offspring    = Parent1;
    Offspring(k) = Parent2(k);

    %% Bit-flip mutation
    Site = rand(N,D) < proM/D;
    Offspring(Site) = ~Offspring(Site);
end

function Offspring = GApermutation(Parent1,Parent2,proC)
% Genetic operators for permutation variables

    %% Order crossover
    [N,D]     = size(Parent1);
    Offspring = Parent1;
    k         = randi(D,1,N);
    for i = 1 : N
        if rand < proC
            Offspring(i,k(i)+1:end) = setdiff(Parent2(i,:),Parent1(i,1:k(i)),'stable');
        end
    end

    %% Slight mutation
    k = randi(D,1,N);
    s = randi(D,1,N);
    for i = 1 : N
        if s(i) < k(i)
            Offspring(i,:) = Offspring(i,[1:s(i)-1,k(i),s(i):k(i)-1,k(i)+1:end]);
        elseif s(i) > k(i)
            Offspring(i,:) = Offspring(i,[1:k(i)-1,k(i)+1:s(i)-1,k(i),s(i):end]);
        end
    end
end


report_this_filefun(mfilename('fullpath'));

% Now lets plot the color-map of the z-value
%
figure

set(gca,'visible','off','FontSize',ZmapGlobal.Data.fontsz.m,'FontWeight','bold',...
    'FontWeight','bold','LineWidth',1.5,...
    'Box','on','SortMethod','childorder')

rect = [0.18,  0.10, 0.7, 0.75];
rect1 = rect;

% set values greater tresh = nan
%
re4 = avm;l = r > tresh; re4(l) = zeros(1,length(find(l)))*nan;

% plot image
%
orient portrait
set(gcf,'PaperPosition', [2. 1 7.0 5.0])

axes('position',rect);hold on
pco1 = pcolor(gx,gy,(re4));
axis([ min(gx) max(gx) min(gy) max(gy)]); axis image; hold on
shading interp;
caxis([2.6 4.00])
if exist('pro', 'var')
    l = pro > 0;
    pro2 = pro;
    pro2(l) = pro2(l)*nan;
    %cs =contour(gx,gy,pro,[ 99 100],'w--');

    % cs =contour(gx,gy,pro,[95 99],'k');
    %[cs, hc] =contour(gx,gy,pro,[ 99 100],'w-');
end % if exist pro
h = hot(64);h = [  h(64:-1:1,:)]; colormap(h)
%end
if fre == 1
    caxis([fix1 fix2])
end

%brighten(0.5)
%xlabel('Distance in [km]','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)
%ylabel('depth in [km]','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)
set(gca,'XTickLabels',[])
set(gca,'YTickLabels',[  10 8 6 4 2])
set(gca,'Color',[0.9 0.9 0.9])

if exist('maex', 'var')
    pl = plot(maex,-maey,'*k');
    set(pl,'MarkerSize',6,'LineWidth',2)
end
overlay

set(gca,'visible','on','FontSize',10,'FontWeight','normal',...
    'FontWeight','normal','LineWidth',1.0,...
    'Box','on','TickDir','out')
h1 = gca;hzma = gca;

% Create a colobar
%
%h5 = colorbar('vertical');
%set(h5,'Pos',[0.25 0.25 0.03 0.25],...
%'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m,'TickDir','out')

% Make the figure visible
%

axes(h1)


function RegMeanSquareVersor(handles, metric)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

global planC stateS;
indexS = planC{end};

    [originF, spacingF, centerF] = getScanOriginSpacing(planC{indexS.scan}(stateS.imageRegistrationBaseDataset));

    [originM, spacingM, centerM] = getScanOriginSpacing(planC{indexS.scan}(stateS.imageRegistrationMovDataset));

    Opt_S_X = str2double(get(handles.versor_s_x, 'string'));
    Opt_S_Y = str2double(get(handles.versor_s_y, 'string'));
    Opt_S_Z = str2double(get(handles.versor_s_z, 'string'));
    tscale  = str2double(get(handles.versor_s_t, 'string'));
    Min_Step_Len = str2double(get(handles.versor_i_minstep, 'string'));
    Max_Step_Len = str2double(get(handles.versor_i_maxstep, 'string'));
    Iteration_Num = str2double(get(handles.versor_i_num, 'string'));

    FImg = planC{indexS.scan}(stateS.imageRegistrationBaseDataset).scanArray;
    MImg = planC{indexS.scan}(stateS.imageRegistrationMovDataset).scanArray;

    dimF = size(FImg);
    dimM = size(MImg);
    %generate cliped base dataset
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_baseTrans'));
    if ~isempty(clipBox)
        FImg = FImg(clipBox(2):clipBox(4), clipBox(1):clipBox(3), :);
        originF(1) = originF(1) + spacingF(1)*double(clipBox(1)-1);
        originF(2) = originF(2) + spacingF(2)*double(uint16(dimF(1)-clipBox(4)));
    end
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_baseSag'));
    if ~isempty(clipBox)
        FImg = FImg(:, :, clipBox(2):clipBox(4));
        originF(3) = originF(3) + spacingF(3)*double(clipBox(2)-1);
    end

    %generate cliped move dataset
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_movTrans'));
    if ~isempty(clipBox)
        MImg = MImg(clipBox(2):clipBox(4), clipBox(1):clipBox(3), :);
        originM(1) = originM(1) + spacingM(1)*double(clipBox(1)-1);
        originM(2) = originM(2) + spacingM(2)*double(uint16(dimM(1)-clipBox(4)));
    end
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_movSag'));
    if ~isempty(clipBox)
        MImg = MImg(:, :, clipBox(2):clipBox(4));
        originM(3) = originM(3) + spacingM(3)*double(clipBox(2)-1);
    end

%downsample the input datasets
    dsampled = 0;
    if (get(handles.dsampleCheck,'Value') == get(handles.dsampleCheck,'Max'))

        tic;
        xyScale =  2; zScale = 2;
        spacingF = [spacingF(1)*xyScale spacingF(2)*xyScale spacingF(3)*zScale];
        spacingM = [spacingM(1)*xyScale spacingM(2)*xyScale spacingM(3)*zScale];
        disp('downSampling ...');
%         FImg = imdesample3d(FImg,xyScale,zScale);
%         MImg = imdesample3d(MImg,xyScale,zScale);
%         FImg=GPReduce2D(FImg,1);
%         MImg=GPReduce2(MImg,1);
        FImg = FImg(1:xyScale:end, 1:xyScale:end, 1:zScale:end);
        MImg = MImg(1:xyScale:end, 1:xyScale:end, 1:zScale:end);

        toc;
        dsampled = 1;
    end

%     call registration method
    switch metric
        case 'mean squares'
            metricIndex = 0;
        case 'normalized correlation'
            metricIndex = 1;
    end

    tic;
tic;

%flip the source datasets on X for itk coordinate system
    fdim = 1;
    FImg = flipdim(FImg, fdim);
    MImg = flipdim(MImg, fdim);

% transform initializing modes 0:MomentON 1:GeometryOn 2:initail transform On
    initMode = get(handles.InitTrans, 'value');

%prepare the initial transform matrix
    transMB = planC{indexS.scan}(stateS.imageRegistrationBaseDataset).transM;
    transMM = planC{indexS.scan}(stateS.imageRegistrationMovDataset).transM;
    if isempty(transMM), transMM = eye(4); end;
    if isempty(transMB), transMB = eye(4); end;
    transM = inv(transMB) * transMM;

%flip the moving dataset to match the initial transM
    Tf = eye(4);
    flipM = 0;
    if (get(handles.flipX, 'value'))
        MImg = flipdim(MImg, 2);
        Tf = [-1 0 0 2*centerM(1); 0 1 0 0; 0 0 1 0; 0 0 0 1];
        flipM = 2;
    end
    if (get(handles.flipY, 'value'))
        MImg = flipdim(MImg, 1);
        Tf = [1 0 0 0; 0 -1 0 2*centerM(2); 0 0 1 0; 0 0 0 1];
        flipM = 1;
    end
    if (get(handles.flipZ, 'value'))
        MImg = flipdim(MImg, 3);
        Tf = [1 0 0 0; 0 1 0 0; 0 0 -1 2*centerM(3); 0 0 0 1];
        flipM = 3;
    end
    transM = transM * inv(Tf);
    rotM = transM(1:3, 1:3); transV = transM(1:3, 4);
    rotM = rotM';
    transV = -transV;

    try
        [im, Rotation, Offset] = VersorRigid3D(int16(FImg), originF, spacingF, ...
                                           int16(MImg), originM, spacingM, ...
                                           Opt_S_X, Opt_S_Y, Opt_S_Z, tscale, Min_Step_Len, Max_Step_Len, ...
                                           Iteration_Num, metricIndex, rotM, transV, initMode);
    catch
        [im, Rotation, Offset] = VersorRigid3D_64(int16(FImg), originF, spacingF, ...
                                           int16(MImg), originM, spacingM, ...
                                           Opt_S_X, Opt_S_Y, Opt_S_Z, tscale, Min_Step_Len, Max_Step_Len, ...
                                           Iteration_Num, metricIndex, rotM, transV, initMode);
    end

    toc;

    im = flipdim(im, fdim);

    output = cell(1, 16);

    output{1} = ['Translation X  = ' num2str(Offset(1))];
    output{2} = ['Translation Y  = ' num2str(Offset(2))];
    output{3} = ['Translation Z  = ' num2str(Offset(3))];
    output{4} = ['Rotation Angle = ' num2str(asin(Rotation(2))*180/pi)];
    output{5} = ['Iterations     = ' num2str(Offset(4))];
    output{6} = ['Metric value   = ' num2str(Offset(5))];
    output{7} = ['RCenter X   = ' num2str(Offset(7))];
    output{8} = ['RCenter Y   = ' num2str(Offset(8))];
    output{9} = ['RCenter Z   = ' num2str(Offset(9))];
    output{10} = ['Offset X   = ' num2str(Offset(10))];
    output{11} = ['Offset Y   = ' num2str(Offset(11))];
    output{12} = ['Offset Z   = ' num2str(Offset(12))];

    set(handles.OutputList, 'string', output);

%update the transM;

    Tv = [Offset(1) Offset(2) Offset(3)];
    Cv = [Offset(7) Offset(8) Offset(9)];
    Cv(3) = -Cv(3); %CERR z axis is opposite to the ITK.

    rot = reshape(Rotation, 3,3);
    offset = [Offset(10) Offset(11) Offset(12)]';

%     rot(2,1) = -rot(2,1); rot(1,2) = -rot(1,2);
%     rot(1,3) = -rot(1,3); rot(3,1) = -rot(3,1);
%     rot(2,3) = -rot(2,3); rot(3,2) = -rot(3,2);
%
%     offset(1) = -offset(1);
%     offset(2) = -offset(2);
%     offset(3) = -offset(3);

    TM = eye(4);
    TM(:,4) = [offset; 1];

    RM = eye(4);
    RM(1:3, 1:3) = rot;

    newTransform = inv(TM*RM);
    newTransform =  transMB * newTransform * Tf;

    scanSetM = stateS.imageRegistrationMovDataset;
    scanSetF = stateS.imageRegistrationBaseDataset;
    planC{indexS.(stateS.imageRegistrationMovDatasetType)}(scanSetM).transM = newTransform;

% save the resampled dataset
    if (get(handles.saveCheck, 'value'))
        if (~dsampled)
            planC{indexS.scan}(end+1) = planC{indexS.scan}(scanSetF);
            planC{indexS.scan}(end).scanArray = im;
        else
            %imReg = resample(scanSetF, scanSetM); % need to up-sample im ????
            planC{indexS.scan}(end+1) = planC{indexS.scan}(scanSetF);
            planC{indexS.scan}(end).scanArray = imReg;
        end
        controlFrame('refresh');
    end

    sliceCallBack('refresh');

end


function [out] = prep_selectTime(dat, varargin)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% prep_selectTime (Pre-processing procedure):
%
% Synopsis:
%     [out] = prep_selectTime(DAT,<OPT>)
%
% Example :
%      out = prep_selectTime(dat, {'Time',[1000 3000]})
%
% Arguments:
%     dat - Structure. epoched data
%     varargin - struct or property/value list of optional properties:
%          : time - Time interval to be selected (ms)
%
% Returns:
%     out - Data structure which has selected time from epoched data
%
%
% Description:
%     This function selects the part of a specific time interval
%     from continuous or epoched data.
%     (i)  For continuous data, this function selects data in specifie time
%      interval from the whole data.
%     (ii) For epoched data, this function selects time interval in each trial.
%      If you want to select trials in specific time interval, you can use
%      a function 'prep_selectTrials'
%     continuous data should be [time * channels]
%     epoched data should be [time * channels * trials]
%
% See also 'https://github.com/PatternRecognition/OpenBMI'
%
% Min-ho Lee, 12-2017
% mh_lee@korea.ac.kr
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if isempty(varargin)
    warning('OpenBMI: Time interval should be specified')
    out = dat;
    return
end
opt = opt_cellToStruct(varargin{:});
if ~isfield(opt,'Time')
    warning('OpenBMI: Time interval should be specified.')
    return
end
ival = opt.Time;

if ~isfield(dat,'x') || ~isfield(dat,'t') || ~isfield(dat,'fs')
    warning('OpenBMI: Data must have fields named ''x'',''t'',''fs''')
    return
end

if isfield(dat,'y_dec') && isfield(dat,'y_logic') && isfield(dat,'y_class')
    a=1;
else
    a=0;
    warning('OpenBMI: Data should have fields named ''y_dec'',''y_logic'',''y_class''')
end

d = ndims(dat.x);
is = ceil(ival(1)*dat.fs/1000);
ie = floor(ival(2)*dat.fs/1000);

if d == 3 || (d==2 && length(dat.chan)==1)
    if ival(1)<dat.ival(1) || ival(2)>dat.ival(end)
        warning('OpenBMI: Selected time interval is out of epoched interval')
        return
    end
    iv = [is:ie]-dat.ival(1)*dat.fs/1000+1;
    x = dat.x(iv,:,:);
    t = dat.t;
%     time = iv/dat.fs*1000; %% Revised hkkim
    time = dat.ival(iv);
    if a
        y_dec = dat.y_dec;
        y_logic = dat.y_logic;
        y_class = dat.y_class;
    end
elseif d == 2 && length(dat.chan)>1
    if ival(1)<0 || ival(2)/1000>size(dat.x,1)/dat.fs
        warning('OpenBMI: Selected time interval is out of time range')
        return
    end
    x = dat.x(is:ie,:);
    s = find((dat.t*1000/dat.fs)>=ival(1));
    e = find((dat.t*1000/dat.fs)<=ival(2));
    iv = s(1):e(end);
    t = dat.t(iv);
    if a
        y_dec = dat.y_dec;
        y_logic = dat.y_logic;
        y_class = dat.y_class;
    end
end
out = rmfield(dat,{'x','t'});
out.x = x;
out.t = t;
if isfield(out,'ival')
    out.ival = time;
end
if a
    out.y_dec = y_dec;
    out.y_logic = y_logic;
    out.y_class = y_class;
end