function varargout = GUI_2D_prestuptepla(varargin)

% Last Modified by GUIDE v2.5 06-Mar-2011 12:28:11

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @GUI_2D_prestuptepla_OpeningFcn, ...
                   'gui_OutputFcn',  @GUI_2D_prestuptepla_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before GUI_2D_prestuptepla is made visible.
function GUI_2D_prestuptepla_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to GUI_2D_prestuptepla (see VARARGIN)

% Choose default command line output for GUI_2D_prestuptepla
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes GUI_2D_prestuptepla wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = GUI_2D_prestuptepla_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

% --- Executes on button press in Run.
function Run_Callback(hObject, eventdata, handles)
clear global
clc

global tkon t

% inputs
ro=str2double(get(handles.hustota,'String'));
vod=str2double(get(handles.vodivost,'String'));
Cp=str2double(get(handles.kapacita,'String'));
T0=str2double(get(handles.T0,'String'));
TH=str2double(get(handles.TH,'String'));
TD=str2double(get(handles.TD,'String'));
TP=str2double(get(handles.TP,'String'));
TL=str2double(get(handles.TL,'String'));
L=str2double(get(handles.L,'String'));
M=str2double(get(handles.M,'String'));
N=str2double(get(handles.n,'String'));
tkon=str2double(get(handles.tkon,'String'));

% calculation ===================================================
a=vod/ro/Cp;
% length step
dx=L/(N-1);
% time step
dt=((dx)^2)/M/a;
t=dt;

% =======================================================
% inicialy temperatures
Tpoc=zeros(N,N);
for i=1:1:N
    for j=1:1:N
        Tpoc(i,j)=T0;
    end
end

while t<tkon

% ============================================================
j=1;
i=1;
Tpoc(i,j)=(Tpoc(i+1,j)+TL+TD+Tpoc(i,j+1)+(M-4)*Tpoc(i,j))/M;

j=N;
i=1;
Tpoc(i,j)=(Tpoc(i+1,j)+TD+Tpoc(i,j-1)+TP+(M-4)*Tpoc(i,j))/M;

j=1;
i=N;
Tpoc(i,j)=(TH+Tpoc(i-1,j)+TL+Tpoc(i,j+1)+(M-4)*Tpoc(i,j))/M;

j=N;
i=N;
Tpoc(i,j)=(TP+Tpoc(i-1,j)+Tpoc(i,j-1)+TP+(M-4)*Tpoc(i,j))/M;

% ==========================================================
i=1;
for j=2:1:N-1
Tpoc(i,j)=(Tpoc(i+1,j)+TD+Tpoc(i,j-1)+Tpoc(i,j+1)+(M-4)*Tpoc(i,j))/M;
end

i=N;
for j=2:1:N-1
    Tpoc(i,j)=(TH+Tpoc(i-1,j)+Tpoc(i,j-1)+Tpoc(i,j+1)+(M-4)*Tpoc(i,j))/M;
end
j=1;
for i=2:1:N-1
    Tpoc(i,j)=(Tpoc(i+1,j)+Tpoc(i-1,j)+TL+Tpoc(i,j+1)+(M-4)*Tpoc(i,j))/M;
end

j=N;
for i=2:1:N-1
    Tpoc(i,j)=(Tpoc(i+1,j)+Tpoc(i-1,j)+Tpoc(i,j-1)+TP+(M-4)*Tpoc(i,j))/M;
end

% ===========================================================
for i=2:1:N-1
    for j=2:1:N-1
        Tpoc(i,j)=(Tpoc(i+1,j)+Tpoc(i-1,j)+Tpoc(i,j-1)+Tpoc(i,j+1)+(M-4)*Tpoc(i,j))/M;
    end
end

% ===========================================================
% graph
pause(0.02)
%axes(handles.graf);
pcolor(Tpoc)
retazec=sprintf('Time=%g s',t);
title(retazec)
colorbar
shading interp

% --------
t=t+dt;
end

function hustota_Callback(hObject, eventdata, handles)
% hObject    handle to hustota (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of hustota as text
%        str2double(get(hObject,'String')) returns contents of hustota as a double

% --- Executes during object creation, after setting all properties.
function hustota_CreateFcn(hObject, eventdata, handles)
% hObject    handle to hustota (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function kapacita_Callback(hObject, eventdata, handles)
% hObject    handle to kapacita (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of kapacita as text
%        str2double(get(hObject,'String')) returns contents of kapacita as a double

% --- Executes during object creation, after setting all properties.
function kapacita_CreateFcn(hObject, eventdata, handles)
% hObject    handle to kapacita (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function vodivost_Callback(hObject, eventdata, handles)
% hObject    handle to vodivost (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of vodivost as text
%        str2double(get(hObject,'String')) returns contents of vodivost as a double

% --- Executes during object creation, after setting all properties.
function vodivost_CreateFcn(hObject, eventdata, handles)
% hObject    handle to vodivost (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function T0_Callback(hObject, eventdata, handles)
% hObject    handle to T0 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of T0 as text
%        str2double(get(hObject,'String')) returns contents of T0 as a double

% --- Executes during object creation, after setting all properties.
function T0_CreateFcn(hObject, eventdata, handles)
% hObject    handle to T0 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function TD_Callback(hObject, eventdata, handles)
% hObject    handle to TD (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of TD as text
%        str2double(get(hObject,'String')) returns contents of TD as a double

% --- Executes during object creation, after setting all properties.
function TD_CreateFcn(hObject, eventdata, handles)
% hObject    handle to TD (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function edit6_Callback(hObject, eventdata, handles)
% hObject    handle to edit6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit6 as text
%        str2double(get(hObject,'String')) returns contents of edit6 as a double

% --- Executes during object creation, after setting all properties.
function edit6_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function TP_Callback(hObject, eventdata, handles)
% hObject    handle to TP (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of TP as text
%        str2double(get(hObject,'String')) returns contents of TP as a double

% --- Executes during object creation, after setting all properties.
function TP_CreateFcn(hObject, eventdata, handles)
% hObject    handle to TP (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function TL_Callback(hObject, eventdata, handles)
% hObject    handle to TL (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of TL as text
%        str2double(get(hObject,'String')) returns contents of TL as a double

% --- Executes during object creation, after setting all properties.
function TL_CreateFcn(hObject, eventdata, handles)
% hObject    handle to TL (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function TH_Callback(hObject, eventdata, handles)
% hObject    handle to TH (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of TH as text
%        str2double(get(hObject,'String')) returns contents of TH as a double

% --- Executes during object creation, after setting all properties.
function TH_CreateFcn(hObject, eventdata, handles)
% hObject    handle to TH (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function M_Callback(hObject, eventdata, handles)
% hObject    handle to M (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of M as text
%        str2double(get(hObject,'String')) returns contents of M as a double

% --- Executes during object creation, after setting all properties.
function M_CreateFcn(hObject, eventdata, handles)
% hObject    handle to M (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function n_Callback(hObject, eventdata, handles)
% hObject    handle to n (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of n as text
%        str2double(get(hObject,'String')) returns contents of n as a double

% --- Executes during object creation, after setting all properties.
function n_CreateFcn(hObject, eventdata, handles)
% hObject    handle to n (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function L_Callback(hObject, eventdata, handles)
% hObject    handle to L (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of L as text
%        str2double(get(hObject,'String')) returns contents of L as a double

% --- Executes during object creation, after setting all properties.
function L_CreateFcn(hObject, eventdata, handles)
% hObject    handle to L (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function tkon_Callback(hObject, eventdata, handles)
% hObject    handle to tkon (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of tkon as text
%        str2double(get(hObject,'String')) returns contents of tkon as a double

% --- Executes during object creation, after setting all properties.
function tkon_CreateFcn(hObject, eventdata, handles)
% hObject    handle to tkon (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global t tkon
t=tkon;
pause(0.02)
clc


%kkgconst 'Generate Object Containing Constant Value Data'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros kgconst.pane file
%
% Parameters:
% Integer: wsize 'Width ', default: 1: 'Width size of constant value data'
% Integer: hsize 'Height ', default: 1: 'Height size of constant value data'
% Integer: dsize 'Depth ', default: 1: 'Depth size of constant value data'
% Integer: tsize 'Time ', default: 1: 'Time size of constant value data'
% Integer: esize 'Elements ', default: 1: 'Element dimension size of constant value data'
% OutputFile: o 'Output', required: 'Output file containing constant value data'
%
% Example: o = kkgconst( {'wsize',1;'hsize',1;'dsize',1;'tsize',1;'esize',1;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% kgconst - Generate Object Containing Constant Value Data
%
%  DESCRIPTION
% .I kgconst
% creates a data object with a constant valued \fBvalue segment" of dimension
% Width * Height * Depth * Time * Elements.
% The data type of the value segment can be
% \fBbit, byte, unsigned byte, short, unsigned short, integer, unsigned integer,
% long, unsigned long, float, double, complex" and \fBdouble complex\fP.
% The real, and imaginary constant levels are specified using the level
% parameters (real, imag).
%
%
%
%  EXAMPLES
% kgconst -o const -wsize 256 -hsize 256 -esize 3 -type integer -real 10
%
% Creates a data object called const of size width = 256, height = 256
% where each vector contains 3 elements.  The data storage type is integer,
% and the constant is 10.
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkgconst(varargin)
Inputs={};
if nargin ==0
  arglist={'',''};
elseif nargin ==1
  arglist=varargin{1};
else error('Usage: [out1,..] = kkgconst(arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'wsize', 1;'hsize', 1;'dsize', 1;'tsize', 1;'esize', 1;'o', '__output'};
maxval={2,2,2,2,2,0};
minval={2,2,2,2,2,0};
istoggle=[1,1,1,1,1,0];
was_set=istoggle * 0;
paramtype={'Integer','Integer','Integer','Integer','Integer','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'kgconst"  '],Inputs,narglist);


% Test for @chebfun/comet.m.

function pass = test_comet(pref)

if ( nargin < 1 )
    pref = chebfunpref();
end

% Real scalar functions.
fsr1 = chebfun(@sin, [-1 0 1], pref);
fsr2 = chebfun(@cos, [-1 0.5 1], pref);

% Obviously, we can't check if the plots are correct without human intervention,
% so all these tests are meant to do is make sure that we don't crash.

hfig = figure('Visible', 'off');

% Check COMET and COMET3.
pass(1) = doesNotCrash(@() comet(fsr1));
pass(2) = doesNotCrash(@() comet(fsr1, fsr2));

close(hfig);

end

function pass = doesNotCrash(fn)

try
    fn();
    pass = true;
catch ME;
    pass = false;
end

end


function [test_failed,fail]=ltfatdiditfail(res,test_failed,tolerance);
%LTFATDIDITFAIL  Did a test fail
%
%  [test_fail,fail]=LTFATDIDITFAIL(res,test_fail) updates test_fail if
%  res is above threshhold and outputs the word FAIL in the variable
%  fail. Use only in testing scripts.
global LTFAT_TEST_TYPE;
if nargin<3
  tolerance=1e-10;
  if strcmpi(LTFAT_TEST_TYPE,'single')
     tolerance=2e-4;
  end
end;

fail='';
if (abs(res)>tolerance) || isnan(res)
  fail='FAILED';
  test_failed=test_failed+1;
end;


% Formatting_step1_cleanup

clear all;close all;clc

code_dir = 'C:\Users\Xiu\Dropbox\FishExplorer';
addpath(genpath(code_dir));

%% Set Manaully!
% file directories
M_dir = GetFishDirectories();
M_tcutoff = {3500,[],[],3500,3600,4000,1800,[],... % Fish 1-8
    [],5000,[],7000,6500,4500, ... % fish 9-14 % fish 12 last ran with []! 1/22/16
    [],2200,[],7000}; % fish 15-18 with GAD in red channel

M_fpsec = {1.97,1.97,1.97,1.97,1.97,1.97,1.97,...% in Hz % Fish 1-7
    1.97,1.93,1.97,1.84,... % Fish 8-11 % Actually Fish 10 freq unrecorded
    2.56,2.33,2.27,... % Fish 12-14
    2.33,2.33,2.38,2.38}; % Fish 15-18

% also check manual frame-correction section below

%%
% poolobj=parpool(8);
%%
range_fish = GetFishRange();

for i_fish = range_fish,
    tic
    disp(['i_fish = ', num2str(i_fish)]);

    fpsec = M_fpsec{i_fish};

    %% load data
    disp(['load data: fish ' num2str(i_fish)]);
    data_dir = M_dir{i_fish};
    if exist(fullfile(data_dir,'cell_resp_dim_lowcut.mat'), 'file'),
        load(fullfile(data_dir,'cell_resp_dim_lowcut.mat'));
    elseif exist(fullfile(data_dir,'cell_resp_dim.mat'), 'file'),
        load(fullfile(data_dir,'cell_resp_dim.mat'));
    else
        errordlg('find data to load!');
    end

    load(fullfile(data_dir,'cell_info.mat'));

    if exist(fullfile(data_dir,'frame_turn_new.mat'), 'file'),
        load(fullfile(data_dir,'frame_turn_new.mat'));
    elseif exist(fullfile(data_dir,'frame_turn.mat'), 'file'),
        load(fullfile(data_dir,'frame_turn.mat'));
    end
    frame_keys = frame_turn;

    if i_fish<12,
        if exist(fullfile(data_dir,'cell_resp_lowcut.stackf'), 'file'),
            TimeSeries = read_LSstack_fast_float(fullfile(data_dir,'cell_resp_lowcut.stackf'),cell_resp_dim);
        elseif exist(fullfile(data_dir,'cell_resp.stackf'), 'file'),
            TimeSeries = read_LSstack_fast_float(fullfile(data_dir,'cell_resp.stackf'),cell_resp_dim);
        else
            errordlg('find data to load!');
        end
    else
        TimeSeries = read_LSstack_fast_float(fullfile(data_dir,'CR_detrend.stackf'),cell_resp_dim);
    end

    %% load anatomy
    tiffname = fullfile(data_dir,'ave.tif');
    info = imfinfo(tiffname,'tiff');
    nPlanes = length(info);
    s1 = info(1).Height;
    s2 = info(1).Width;
    ave_stack = zeros(s1,s2,nPlanes);
    for i=1:nPlanes,
        ave_stack(:,:,i) = imread(tiffname,i);
    end

    %% fix the left-right flip in the anatomy stack and subsequent cell_info
    anat_stack = fliplr(ave_stack);
    %     anat_stack(:,113:1092,:) = anat_stackCopy;

    [s1,s2,~] = size(anat_stack);
    for i_cell = 1:length(cell_info),
        % fix '.center'
        cell_info(i_cell).center(2) = s2-cell_info(i_cell).center(2)+1; %#ok<*SAGROW>
    end

    %% reformat coordinates
    numcell_full = cell_resp_dim(1);
    temp = [cell_info(:).center];
    XY = reshape(temp',[],numcell_full)';
    Z = [cell_info.slice]';
    CellXYZ = horzcat(XY,Z);

%     %% Manual occasional frame corrections: ONLY RUN ONCE!!!!!!!!!
%
%     if true,
%         % add 1 frame at start: ------------- for which fish again? all till F11?
%         cell_resp_full = horzcat(cell_resp_full(:,1),cell_resp_full);
%         frame_keys = vertcat(frame_keys(1,:),frame_keys);
%     end
%
%     % correction of an error in Fish #1
%     if i_fish == 1,
%         cell_resp_full = horzcat(cell_resp_full(:,1:20),cell_resp_full);
%     end
%
    %% Crop end of experiment (when cell-segmentation drift > ~1um, manually determined)
    if i_fish==13,
        TimeSeries = TimeSeries(:,305:end);
    end

    if ~isempty(M_tcutoff{i_fish}),
        TimeSeries = TimeSeries(:,1:M_tcutoff{i_fish});
%         cell_resp_full = cell_resp_full(:,1:M_tcutoff{i_fish});
        frame_keys = frame_keys(1:M_tcutoff{i_fish},:);
    end

    %% detrend
%     CR_dtr = zeros(size(cell_resp_full));
%     tmax=size(cell_resp_full,2);
%     numcell_full=size(cell_resp_full,1);
%
%     parfor i=1:numcell_full,
%         cr = cell_resp_full(i,:);
%         crd = 0*cr;
%         for j=1:100:tmax,
%             if j<=150,
%                 tlim1 = 1;
%                 tlim2 = 300;
%             elseif j>tmax-150,
%                 tlim1 = tmax-300;
%                 tlim2 = tmax;
%             else
%                 tlim1 = j-150;
%                 tlim2 = j+150;
%             end
%             crr = cr(tlim1:tlim2);
%             crd(max(1,j-50):min(tmax,j+50)) = prctile(crr,15);
%         end
% %         if mod(i,100)==0,
% %             disp(num2str(i));
% %         end
%         CR_dtr(i,:) = cr-crd;
%     end
%
%     TimeSeries = single(CR_dtr);

    %% registered coordinates from morphing to ZBrain
    if i_fish<=18,
        [CellXYZ_norm,IX_inval_norm] = GetNormCellCord(i_fish);
    else % place holder
        CellXYZ_norm = CellXYZ;
        IX_inval_norm = [];
    end

    %% Save files
tic
    % directory to save data formatted for distribution:
    save_masterdir = GetNestedDataDir();
    save_dir = fullfile(save_masterdir,['subject_' num2str(i_fish)]);
    if ~exist(save_dir, 'dir')
        mkdir(save_dir);
    end

    % save time-series
    h5create(fullfile(save_dir,'TimeSeries.h5'),'/TimeSeries',size(TimeSeries),'Datatype','single','ChunkSize',[1000 100]);
    h5write(fullfile(save_dir,'TimeSeries.h5'),'/TimeSeries',TimeSeries);

    % save .mat files
    filename = fullfile(save_dir,'CoreInfo.mat');
    varList = {'CellXYZ','anat_stack','fpsec'};
    save(filename,varList{:});

    filename = fullfile(save_dir,'OptionalInfo.mat');
    varList = {'numcell_full','CellXYZ_norm','IX_inval_norm'};
    save(filename,varList{:});

    filename = fullfile(save_dir,'AdditionalInfo.mat');
    save(filename,'frame_keys');
toc
    %%
    toc
end

%%
% delete(poolobj);


function CPD = reset_ess(CPD)
% RESET_ESS Reset the Expected Sufficient Statistics for a CPD (mlp)
% CPD = reset_ess(CPD)

CPD.W1 = [];
CPD.W2 = [];
CPD.b1 = [];
CPD.b2 = [];
CPD.parent_vals = [];
CPD.eso_weights=[];
CPD.self_vals = [];
CPD.nsamples = 0;


function [subj_descriptives, event_descriptives] = get_descriptives(D, varargin)
% Returns descriptive stats for every variable, or specified variables
%
% :Usage:
% ::
%
%    print_summary(D, [optional inputs])
%
% ..
%     Author and copyright information:
%
%     Copyright (C) 2013 Tor Wager
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
% ..
%
%
% :Inputs:
%
%   **D:**
%        a canlab_dataset object
%
% :Optional Inputs:
%
%   **subj:**
%        followed by a cell array of subject level var names, to only see those vars
%
%   **event:**
%        followed by a cell array of event level var names, to only see those vars
%
%   if either varargin is unspecified, all variables will be printed
%
% Examples:
%
% % Get descriptive stats in tables all variables in canalab_dataset object D
% [subj_descriptives, event_descriptives] = get_descriptives(D, 'event', 'temp')
%
% Get descriptive stats in tables for the Event_Level variable 'temp'
% [subj_descriptives, event_descriptives] = get_descriptives(D, 'event', 'temp')
%
% Get descriptive stats in tables for the Event_Level variables 'temp' and 'ratings'
%[subj_descriptives, event_descriptives] = get_descriptives(D, 'event', {'temp' 'ratings'})

subj_descriptives = table;
event_descriptives = table;

% Default: All variables
subj_varnames = D.Subj_Level.names;
if iscolumn(subj_varnames), subj_varnames = subj_varnames'; end % need row

event_varnames = D.Event_Level.names;
if iscolumn(event_varnames), event_varnames = event_varnames'; end % need row

svars = find(strcmp('subj', varargin));
evars = find(strcmp('event', varargin));

if ~isempty(svars) || ~isempty(evars)
    % Replace default lists with input variables only
    [subj_varnames, event_varnames] = deal({});
end

% Subject level
% -------------------------------------------------------------------------

if ~isempty(svars), subj_varnames = varargin{svars+1}; end
if ~isempty(svars) && ~iscell(subj_varnames), subj_varnames = {subj_varnames}; end

Var_name = subj_varnames';
clear Min_value Max_value Mean_value St_Dev IQR NaN_count

for i=1:length(subj_varnames)

    vname = subj_varnames{i};

    [Min_value(i, 1) Max_value(i, 1) Mean_value(i, 1) St_Dev(i, 1) IQR(i, 1) NaN_count(i, 1), text_vals] = get_descriptives_var(D, vname);

end

if length(subj_varnames) > 0
    subj_descriptives = table(Var_name, Min_value, Max_value, Mean_value, St_Dev, IQR, NaN_count);
end

% Event level
% -------------------------------------------------------------------------
if ~isempty(evars), event_varnames = varargin{evars+1}; end
if ~isempty(evars) && ~iscell(event_varnames), event_varnames = {event_varnames}; end

Var_name = event_varnames';
clear Min_value Max_value Mean_value St_Dev IQR NaN_count

for i=1:length(event_varnames)

    vname = event_varnames{i};

    [Min_value(i, 1) Max_value(i, 1) Mean_value(i, 1) St_Dev(i, 1) IQR(i, 1) NaN_count(i, 1), text_vals] = get_descriptives_var(D, vname);

end

if length(event_varnames) > 0
    event_descriptives = table(Var_name, Min_value, Max_value, Mean_value, St_Dev, IQR, NaN_count);
end

end % main function

function [Min_value, Max_value, Mean_value, St_Dev, myIQR, NaN_count, text_vals] = get_descriptives_var(D, vname)

% intialize
[Min_value, Max_value, Mean_value, St_Dev, myIQR, NaN_count] = deal(NaN);
text_vals = [];

[var, varcell, ~, descrip] = get_var(D, vname);

if isempty(var)
    return
end

if ismatrix(var)
    % Happens when this is Event_Level var with same number of events for
    % all subjects; or padded with NaNs.
    var = var(:);
end

if ischar(var)
    % This happens for event-level variables with different numbers of
    % observations for different cells. This issue may be removed in the
    % future, however.

    if iscell(varcell{1})
        fprintf('%s (%s): Cell array. Length of first cell: %d\t\n', ...
        vname, descrip, length(varcell{1}));

    else

        var = double(cat(1, varcell{:}));

    end
end

if iscell(var)  % SHOULD BE DEPRECATED - need to handle text differently
    % istext

    % check for some (partial) empty vars
    is_empty = cellfun(@isempty, var);
    num_empty = sum(is_empty);

    if num_empty > 0 && num_empty < length(var)
        warning(sprintf('Some values of %s are missing.', vname))
    end

    fprintf('%s (%s): Text. Unique values: %d\t\n', ...
        vname, descrip, length(unique(var(~is_empty))));

else
    % Standard Subj-level and Event-level vars with same no. of obs.
    % isnumeric
    Min_value = min(var);
    Max_value = max(var);
    Mean_value = nanmean(var);
    St_Dev = nanstd(var);
    myIQR = iqr(var);
    NaN_count = sum(isnan(var));
end

end


function msg = comparisonMessage(user_message, assertion_message, A, B)
%comparisonMessage Generate assertion message when comparing two arrays.
%   msg = comparisonMessage(user_message, assertion_message, A, B) returns a
%   string appropriate to use in a call to throw inside an assertion function
%   that compares two arrays A and B.
%
%   The string returned has the following form:
%
%       <user_message>
%       <assertion_message>
%
%       First input:
%       <string representation of value of A>
%
%       Second input:
%       <string representation of value of B>
%
%   user_message can be the empty string, '', in which case user_message is
%   skipped.

%   Steven L. Eddins
%   Copyright 2009 The MathWorks, Inc.

msg = sprintf('%s\n\n%s\n%s\n\n%s\n%s', ...
    assertion_message, ...
    'First input:', ...
    xunit.utils.arrayToString(A), ...
    'Second input:', ...
    xunit.utils.arrayToString(B));

if ~isempty(user_message)
    msg = sprintf('%s\n%s', user_message, msg);
end


function mri = ctf_avw2mri(avw)

% mri = ctf_avw2mri(avw)
%
% The purpose of this function is to convert an Analyze volume into a CTF
% .mri volume.  It currently requires that the Analyze volume is
% 256x256x256, 1x1x1 mm voxels.  The avw_read function can
% handle various Analyze orientations, so this function assumes that the
% avw.img volume has axial unflipped orientation (it always is when
% returned by avw_read, regardless of the format in the .img file). The
% returned mri struct in the matlab workspace can be saved using
% ctf_write_mri.
%
% This function depends on the avw* functions availabe in the mri_toolbox
% at http://eeg.sf.net/.  In particular, the avw_read and associated
% functions for reading an Analyze volume into a matlab avw struct, used as
% input to this function.
%
%      <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %
%      <                                                      > %
%      <                    DISCLAIMER:                       > %
%      <                                                      > %
%      < THIS PROGRAM IS INTENDED FOR RESEARCH PURPOSES ONLY. > %
%      < THIS PROGRAM IS IN NO WAY INTENDED FOR CLINICAL OR   > %
%      <                    OFFICIAL USE.                     > %
%      <                                                      > %
%      <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> %
%

% $Revision: 1.1 $ $Date: 2009-01-30 03:49:26 $

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

% History:  08/2003, Darren.Weber_at_radiology.ucsf.edu
%                    - adapted from an appendex to CTF document
%                    MRIConverter.pdf, which is copied at the end of this
%                    function.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mri = ctf_mri_make;

mri.file = [avw.fileprefix,'.mri'];

ver = '[$Revision: 1.1 $]';
fprintf('\nCTF_AVW2MRI [v%s]\n',ver(12:16));  tic;

% these checks for the volume dims/pixel size could be replaced with an
% interpolation function that could take any Analyze volume and convert it
% to 256x256x256, 1x1x1 mm
if avw.hdr.dime.dim(2) ~= 256,
    error('avw.hdr.dime.dim(2) ~= 256');
end
if avw.hdr.dime.dim(3) ~= 256,
    error('avw.hdr.dime.dim(3) ~= 256');
end
if avw.hdr.dime.dim(4) ~= 256,
    error('avw.hdr.dime.dim(4) ~= 256');
end

if avw.hdr.dime.pixdim(2) ~= 1,
    error('avw.hdr.dime.dim(2) ~= 256');
end
if avw.hdr.dime.pixdim(3) ~= 1,
    error('avw.hdr.dime.dim(3) ~= 256');
end
if avw.hdr.dime.pixdim(4) ~= 1,
    error('avw.hdr.dime.dim(4) ~= 256');
end

% mri.hdr.dataSize = 1 or 2 (bytes), 8 or 16 bits
if avw.hdr.dime.bitpix == 8,
    mri.hdr.dataSize = 1;
    mri.hdr.clippingRange = 255;
else
    mri.hdr.dataSize = 2;
    mri.hdr.clippingRange = 65536;
end

% This next step should always work correctly, given that avw_read always
% converts any Analyze orientation into axial unflipped in the matlab
% workspace variable avw.img; the axial unflipped orientation is
% (+X left,  +Y anterior,  +Z superior); the ctf orientation is
% (+X right, +Y posterior, +Z inferior), the complete opposite.
temp = flipdim(avw.img,1);
temp = flipdim(temp,2);
temp = flipdim(temp,3);
mri.img = temp;

t=toc; fprintf('...done (%5.2f sec).\n\n',t);

return


function [vol, sens] = ft_prepare_vol_sens(vol, sens, varargin)

% FT_PREPARE_VOL_SENS does some bookkeeping to ensure that the volume
% conductor model and the sensor array are ready for subsequent forward
% leadfield computations. It takes care of some pre-computations that can
% be done efficiently prior to the leadfield calculations.
%
% Use as
%   [vol, sens] = ft_prepare_vol_sens(vol, sens, ...)
% with input arguments
%   sens   structure with gradiometer or electrode definition
%   vol    structure with volume conductor definition
%
% The vol structure represents a volume conductor model, its contents
% depend on the type of model. The sens structure represents a sensor
% array, i.e. EEG electrodes or MEG gradiometers.
%
% Additional options should be specified in key-value pairs and can be
%   'channel'    cell-array with strings (default = 'all')
%   'order'      number, for single shell "Nolte" model (default = 10)
%
% The detailled behaviour of this function depends on whether the input
% consists of EEG or MEG and furthermoree depends on the type of volume
% conductor model:
% - in case of EEG single and concentric sphere models, the electrodes are
%   projected onto the skin surface.
% - in case of EEG boundary element models, the electrodes are projected on
%   the surface and a blilinear interpoaltion matrix from vertices to
%   electrodes is computed.
% - in case of MEG and a multispheres model, a local sphere is determined
%   for each coil in the gradiometer definition.
%  - in case of MEG with a singleshell Nolte model, the volume conduction
%    model is initialized
% In any case channel selection and reordering will be done. The channel
% order returned by this function corresponds to the order in the 'channel'
% option, or if not specified, to the order in the input sensor array.
%
% See also FT_READ_VOL, FT_READ_SENS, FT_TRANSFORM_VOL, FT_TRANSFORM_SENS, FT_COMPUTE_LEADFIELD

% Copyright (C) 2004-2009, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: ft_prepare_vol_sens.m 2833 2011-02-06 20:19:54Z crimic $

% get the options
% fileformat = keyval('fileformat',  varargin);
channel = keyval('channel',  varargin);  % cell-array with channel labels
order   = keyval('order',    varargin);  % order of expansion for Nolte method; 10 should be enough for real applications; in simulations it makes sense to go higher

% set the defaults
if isempty(channel),  channel = sens.label;   end
if isempty(order),    order = 10;             end

% determine whether the input contains EEG or MEG sensors
iseeg = ft_senstype(sens, 'eeg');
ismeg = ft_senstype(sens, 'meg');

% determine the skin compartment
if ~isfield(vol, 'skin_surface')
  if isfield(vol, 'bnd')
    vol.skin_surface   = find_outermost_boundary(vol.bnd);
  elseif isfield(vol, 'r') && length(vol.r)<=4
    [dum, vol.skin_surface] = max(vol.r);
  end
end

% determine the inner_skull_surface compartment
if ~isfield(vol, 'inner_skull_surface')
  if isfield(vol, 'bnd')
    vol.inner_skull_surface  = find_innermost_boundary(vol.bnd);
  elseif isfield(vol, 'r') && length(vol.r)<=4
    [dum, vol.inner_skull_surface] = min(vol.r);
  end
end

% otherwise the voltype assignment to an empty struct below won't work
if isempty(vol)
  vol = [];
end

% this makes them easier to recognise
sens.type = ft_senstype(sens);
vol.type  = ft_voltype(vol);

if isfield(vol, 'unit') && isfield(sens, 'unit') && ~strcmp(vol.unit, sens.unit)
  error('inconsistency in the units of the volume conductor and the sensor array');
end

if ismeg && iseeg
  % this is something that could be implemented relatively easily
  error('simultaneous EEG and MEG not yet supported');

elseif ~ismeg && ~iseeg
  error('the input does not look like EEG, nor like MEG');

elseif ismeg

  % keep a copy of the original sensor array, this is needed for the MEG multisphere model
  sens_orig = sens;

  % always ensure that there is a linear transfer matrix for combining the coils into gradiometers
  if ~isfield(sens, 'tra');
    Nchans = length(sens.label);
    Ncoils = size(sens.pnt,1);
    if Nchans~=Ncoils
      error('inconsistent number of channels and coils');
    end
    sens.tra = sparse(eye(Nchans, Ncoils));
  end

  % select the desired channels from the gradiometer array
  % order them according to the users specification
  [selchan, selsens] = match_str(channel, sens.label);

  % first only modify the linear combination of coils into channels
  sens.label = sens.label(selsens);
  sens.tra   = sens.tra(selsens,:);
  % subsequently remove the coils that do not contribute to any sensor output
  selcoil  = find(sum(sens.tra,1)~=0);
  sens.pnt = sens.pnt(selcoil,:);
  sens.ori = sens.ori(selcoil,:);
  sens.tra = sens.tra(:,selcoil);

  switch ft_voltype(vol)
    case 'infinite'
      % nothing to do

    case 'singlesphere'
      % nothing to do

    case 'concentric'
      % nothing to do

    case 'neuromag'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % if the forward model is computed using the external Neuromag toolbox,
      % we have to add a selection of the channels so that the channels
      % in the forward model correspond with those in the data.
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      [selchan, selsens] = match_str(channel, sens.label);
      vol.chansel = selsens;

    case 'multisphere'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % If the volume conduction model consists of multiple spheres then we
      % have to match the channels in the gradiometer array and the volume
      % conduction model.
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      % use the original sensor array instead of the one with a subset of
      % channels, because we need the complete mapping of coils to channels
      sens = sens_orig;

      % remove the coils that do not contribute to any channel output
      % since these do not have a corresponding sphere
      selcoil  = find(sum(sens.tra,1)~=0);
      sens.pnt = sens.pnt(selcoil,:);
      sens.ori = sens.ori(selcoil,:);
      sens.tra = sens.tra(:,selcoil);

      % the initial multisphere volume conductor has a local sphere per
      % channel, whereas it should have a local sphere for each coil
      if size(vol.r,1)==size(sens.pnt,1) && ~isfield(vol, 'label')
        % it appears that each coil already has a sphere, which suggests
        % that the volume conductor already has been prepared to match the
        % sensor array
        return
      elseif size(vol.r,1)==size(sens.pnt,1) && isfield(vol, 'label')
        if ~isequal(vol.label(:), sens.label(:))
          % if only the order is different, it would be possible to reorder them
          error('the coils in the volume conduction model do not correspond to the sensor array');
        else
          % the coil-specific spheres in the volume conductor should not have a label
          % because the label is already specified for the coils in the
          % sensor array
          vol = rmfield(vol, 'label');
        end
        return
      end

      % the CTF way of representing the headmodel is one-sphere-per-channel
      % whereas the FieldTrip way of doing the forward computation is one-sphere-per-coil
      Nchans   = size(sens.tra,1);
      Ncoils   = size(sens.tra,2);
      Nspheres = size(vol.label);

      if isfield(vol, 'orig')
        % these are present in a CTF *.hdm file
        singlesphere.o(1,1) = vol.orig.MEG_Sphere.ORIGIN_X;
        singlesphere.o(1,2) = vol.orig.MEG_Sphere.ORIGIN_Y;
        singlesphere.o(1,3) = vol.orig.MEG_Sphere.ORIGIN_Z;
        singlesphere.r      = vol.orig.MEG_Sphere.RADIUS;
        % ensure consistent units
        singlesphere = ft_convert_units(singlesphere, vol.unit);
        % determine the channels that do not have a corresponding sphere
        % and use the globally fitted single sphere for those
        missing = setdiff(sens.label, vol.label);
        if ~isempty(missing)
          warning('using the global fitted single sphere for %d channels that do not have a local sphere', length(missing));
        end
        for i=1:length(missing)
          vol.label(end+1) = missing(i);
          vol.r(end+1,:)   = singlesphere.r;
          vol.o(end+1,:)   = singlesphere.o;
        end
      end

      multisphere = [];
      % for each coil in the MEG helmet, determine the corresponding channel and from that the corresponding local sphere
      for i=1:Ncoils
        coilindex = find(sens.tra(:,i)~=0); % to which channel does this coil belong
        if length(coilindex)>1
          % this indicates that there are multiple channels to which this coil contributes,
          % which happens if the sensor array represents a synthetic higher-order gradient.
          [dum, coilindex] = max(abs(sens.tra(:,i)));
        end

        coillabel = sens.label{coilindex};                    % what is the label of this channel
        chanindex = strmatch(coillabel, vol.label, 'exact');  % what is the index of this channel in the list of local spheres
        multisphere.r(i,:) = vol.r(chanindex);
        multisphere.o(i,:) = vol.o(chanindex,:);
      end
      vol = multisphere;

      % finally do the selection of channels and coils
      % order them according to the users specification
      [selchan, selsens] = match_str(channel, sens.label);

      % first only modify the linear combination of coils into channels
      sens.label = sens.label(selsens);
      sens.tra   = sens.tra(selsens,:);
      % subsequently remove the coils that do not contribute to any sensor output
      selcoil  = find(sum(sens.tra,1)~=0);
      sens.pnt = sens.pnt(selcoil,:);
      sens.ori = sens.ori(selcoil,:);
      sens.tra = sens.tra(:,selcoil);
      % make the same selection of coils in the multisphere model
      vol.r = vol.r(selcoil);
      vol.o = vol.o(selcoil,:);

    case 'nolte'
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % if the forward model is computed using the code from Guido Nolte, we
      % have to initialize the volume model using the gradiometer coil
      % locations
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      % compute the surface normals for each vertex point
      if ~isfield(vol.bnd, 'nrm')
        fprintf('computing surface normals\n');
        vol.bnd.nrm = normals(vol.bnd.pnt, vol.bnd.tri);
      end

      % estimate center and radius
      [center,radius] = fitsphere(vol.bnd.pnt);

      % initialize the forward calculation (only if gradiometer coils are available)
      if size(sens.pnt,1)>0
        vol.forwpar = meg_ini([vol.bnd.pnt vol.bnd.nrm], center', order, [sens.pnt sens.ori]);
      end

    case 'openmeeg'
        % nothing ?

    otherwise
      error('unsupported volume conductor model for MEG');
  end

elseif iseeg
  % select the desired channels from the electrode array
  % order them according to the users specification
  if ~isfield(sens, 'tra')
     Nchans    = length(sens.label);
     Ncontacts = length(sens.label);
  else
     Nchans    = size(sens.tra,1);
     Ncontacts = size(sens.tra,2);
  end;

  % In case of Nchans~=Ncontacts it is difficult to determine
  % how to deal with contacts positions (keep the original positions)
  if Nchans == Ncontacts
    [selchan, selsens] = match_str(channel, sens.label);
    sens.label = sens.label(selsens);
    sens.pnt = sens.pnt(selsens,:);
  else
    warning('A sub-selection of channels will not be taken into account')
  end

  % create a 2D projection and triangulation
  try
    sens.prj   = elproj(sens.pnt);
    sens.tri   = delaunay(sens.prj(:,1), sens.prj(:,2));
  catch
    warning('2D projection not done')
  end

  switch ft_voltype(vol)
    case 'infinite'
      % nothing to do

    case 'halfspace'
      pnt    = sens.pnt;
      if ft_voltype(vol,'halfspace')
        d = dist(pnt);
        % scan the electrodes and reposition the ones which are in the
        % wrong halfspace (projected on the plane)
        for i=1:size(pnt,1)
          P = pnt(i,:);
          is_in_empty = acos(dot(vol.ori,(P-vol.pnt)./norm(P-vol.pnt))) < pi/2;
          if is_in_empty
            d = dist(P);
            dPplane = -dot(vol.ori, vol.pnt-P, 2);
            if dPplane>median(d(:))
              error('Some electrodes are too distant from the plane: consider repositioning them')
            else
              % project point on plane
              Ppr  = [0 0 0];
              line = [P vol.ori];
              % get indices of line and plane which are parallel
              par = abs(dot(vol.ori, line(:,4:6), 2))<1e-14;
              % difference between origins of plane and line
              dp = vol.pnt - line(:, 1:3);
              % Divide only for non parallel vectors (DL)
              t = dot(vol.ori(~par,:), dp(~par,:), 2)./dot(vol.ori(~par,:), line(~par,4:6), 2);
              % compute coord of intersection point
              Ppr(~par, :) = line(~par,1:3) + repmat(t,1,3).*line(~par,4:6);
              pnt(i,:) = Ppr;
            end
          end
        end
        sens.pnt = pnt;
      else
        error('Wrong volume type')
      end

    case {'singlesphere', 'concentric'}
      % ensure that the electrodes ly on the skin surface
      radius = max(vol.r);
      pnt    = sens.pnt;
      if isfield(vol, 'o')
        % shift the the centre of the sphere to the origin
        pnt(:,1) = pnt(:,1) - vol.o(1);
        pnt(:,2) = pnt(:,2) - vol.o(2);
        pnt(:,3) = pnt(:,3) - vol.o(3);
      end
      distance = sqrt(sum(pnt.^2,2)); % to the center of the sphere
      if any((abs(distance-radius)/radius)>0.005)
        warning('electrodes do not lie on skin surface -> using radial projection')
      end
      pnt = pnt * radius ./ [distance distance distance];
      if isfield(vol, 'o')
        % shift the center back to the original location
        pnt(:,1) = pnt(:,1) + vol.o(1);
        pnt(:,2) = pnt(:,2) + vol.o(2);
        pnt(:,3) = pnt(:,3) + vol.o(3);
      end
      sens.pnt = pnt;

    case {'bem', 'dipoli', 'asa', 'avo', 'bemcp', 'openmeeg'}
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      % do postprocessing of volume and electrodes in case of BEM model
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      % project the electrodes on the skin and determine the bilinear interpolation matrix
      if ~isfield(vol, 'tra')
        % determine boundary corresponding with skin and inner_skull_surface
        if ~isfield(vol, 'skin_surface')
          vol.skin_surface = find_outermost_boundary(vol.bnd);
          fprintf('determining skin compartment (%d)\n', vol.skin_surface);
        end
        if ~isfield(vol, 'source')
          vol.source = find_innermost_boundary(vol.bnd);
          fprintf('determining source compartment (%d)\n', vol.source);
        end
        if size(vol.mat,1)~=size(vol.mat,2) && size(vol.mat,1)==length(sens.pnt)
          fprintf('electrode transfer and system matrix were already combined\n');
        else
          fprintf('projecting electrodes on skin surface\n');
          % compute linear interpolation from triangle vertices towards electrodes
          [el, prj] = project_elec(sens.pnt, vol.bnd(vol.skin_surface).pnt, vol.bnd(vol.skin_surface).tri);
          tra       = transfer_elec(vol.bnd(vol.skin_surface).pnt, vol.bnd(vol.skin_surface).tri, el);

          % replace the original electrode positions by the projected positions
          sens.pnt = prj;

          if size(vol.mat,1)==size(vol.bnd(vol.skin_surface).pnt,1)
            % construct the transfer from only the skin vertices towards electrodes
            interp = tra;
          else
            % construct the transfer from all vertices (also inner_skull_surface/outer_skull_surface) towards electrodes
            interp = [];
            for i=1:length(vol.bnd)
              if i==vol.skin_surface
                interp = [interp, tra];
              else
                interp = [interp, zeros(size(el,1), size(vol.bnd(i).pnt,1))];
              end
            end
          end

          % incorporate the linear interpolation matrix and the system matrix into one matrix
          % this speeds up the subsequent repeated leadfield computations
          fprintf('combining electrode transfer and system matrix\n');
          if strcmp(ft_voltype(vol), 'openmeeg')
            nb_points_external_surface = size(vol.bnd(vol.skin_surface).pnt,1);
            vol.mat = vol.mat((end-nb_points_external_surface+1):end,:);
            vol.mat = interp(:,1:nb_points_external_surface) * vol.mat;
          else
            % convert to sparse matrix to speed up the subsequent multiplication
            interp  = sparse(interp);
            vol.mat = interp * vol.mat;
            % ensure that the model potential will be average referenced
            avg = mean(vol.mat, 1);
            vol.mat = vol.mat - repmat(avg, size(vol.mat,1), 1);
          end
        end
      end

    otherwise
      error('unsupported volume conductor model for EEG');
  end

  % FIXME this needs carefull thought to ensure that the average referencing which is now done here and there, and that the linear interpolation in case of BEM are all dealt with consistently
  % % always ensure that there is a linear transfer matrix for
  % % rereferencing the EEG potential
  % if ~isfield(sens, 'tra');
  %   sens.tra = sparse(eye(length(sens.label)));
  % end

end % if iseeg or ismeg


function [ STATEints ] = IDStateEpisode(STATEints,maxintdur,minSTATEdur)
%UNTITLED Summary of this function goes here
%   Detailed explanation goes here
%
%INPUTS
%   STATEints
%   maxintdur   maximum interruption
%   minSTATEdur minimum state duration

%%
%SWSints = stateintervals{2};

[STATEints] = MergeSeparatedInts_ss(STATEints,maxintdur);
STATElengths = STATEints(:,2)-STATEints(:,1);
STATEints = STATEints(STATElengths>=minSTATEdur,:);

end


function [ model ] = initFBAFields( model, printLevel )
% This function initializes all fields in a model that are required for
% downstream FBA analysis. It does so if and only if a Stoichiometric
% matrix S is provided.
%
% USAGE:
%    model = convertOldStyleModel(model, printLevel)
%
% INPUT:
%    model:         a COBRA Model structure with at least the model.S field.
%                   All fields already present are retained and absent
%                   fields are initialized with their defaults.
%
% OPTIONAL INPUT:
%    printLevel:    indicates whether warnings and messages are given (default, 1).
%
% OUTPUT:
%    model:         a COBRA model struct with the following fields:
%                   .S (same as input)
%                   .rxns (default: a vector of strings R1 .. R size(S,2)
%                   .mets (default: a vector of strings M1 .. M size(S,1)
%                   .lb   (default: -1000 * ones(size(S,2),1) );
%                   .ub   (default: 1000 * ones(size(S,2),1) );
%                   .genes   (default: cell(0,1));
%                   .rules   (default: repmat({''},size(S,2),1))
%                   .osense (default: -1)
%                   .csense (default: a char vector of 'E' of the size size(S,1) x 1)
%
% .. Author: - Thomas Pfau Nov 2017

if ~isfield(model,'S')
    error('Cannot create FBA fields without stoichiometric matrix');
else
    %Init basic sizes
    rxns = size(model.S,2);
    mets = size(model.S,1);
    genes = 0;
end

structfields = fieldnames(model);
optionalFields = getDefinedFieldProperties();
fluxConsistencyFields = optionalFields(cellfun(@(x) x, optionalFields(:,6)),:);

for field = 1:size(fluxConsistencyFields,1)
    cfieldName = fluxConsistencyFields{field,1};
    if ~any(ismember(structfields,cfieldName))

        csize1 = fluxConsistencyFields{field,2};
        if ischar(csize1)
            eval(['csize1 = ' fluxConsistencyFields{field,2} ';']);
        end
        csize2 = fluxConsistencyFields{field,3};
        if ischar(csize2)
            eval(['csize2 = ' fluxConsistencyFields{field,3} ';']);
        end

        i = 0;
        defaultVal = fluxConsistencyFields{field,5};
        isCellEntry = false;
        if ischar(defaultVal)
            if strfind('iscell',fluxConsistencyFields(field,4))
                eval(['defaultVal = ' fluxConsistencyFields{field,5} ';']);
            else
                defaultVal = fluxConsistencyFields{field,5};
            end
            isCellEntry = true;
        end
        if ~isCellEntry
            cfield = zeros(csize1,csize2);
            for i = 1:csize1
                cfield(i) = fluxConsistencyFields{field,5};
            end
            model.(cfieldName) = cfield;
        else
            %Lets also check for this being a char.
            if isequal(fluxConsistencyFields{field,4},'ischar(x)')
                cfield = repmat(defaultVal,csize1,csize2);
                model.(cfieldName) = cfield;
            else

                cfield = cell(csize1,csize2);
                for i = 1:csize1
                    eval(['cfield{i} = ' fluxConsistencyFields{field,5} ';']);
                end
                model.(cfieldName) = cfield;
            end
        end
    end
end


function varargout = spm_preproc_run(job,action)
% Segment a bunch of images
% FORMAT spm_preproc_run(job)
% job.channel(n).vols{m}
% job.channel(n).biasreg
% job.channel(n).biasfwhm
% job.channel(n).write
% job.tissue(k).tpm
% job.tissue(k).ngaus
% job.tissue(k).native
% job.tissue(k).warped
% job.warp.mrf
% job.warp.cleanup
% job.warp.affreg
% job.warp.reg
% job.warp.fwhm
% job.warp.samp
% job.warp.write
% job.warp.bb
% job.warp.vox
% job.iterations
% job.alpha
%
% See the batch interface for a description of the fields.
%
% See also spm_preproc8.m amd spm_preproc_write8.m
%__________________________________________________________________________
% Copyright (C) 2008-2015 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_preproc_run.m 7670 2019-10-01 16:55:13Z john $

SVNid = '$Rev: 7670 $';

if nargin == 1, action = 'run'; end

switch lower(action)
    case 'run'
        spm('FnBanner',mfilename,SVNid);
        varargout{1} = run_job(job);
        fprintf('%-40s: %30s\n','Completed',spm('time'))                %-#
    case 'check'
        varargout{1} = check_job(job);
    case 'vfiles'
        varargout{1} = vfiles_job(job);
    case 'vout'
        varargout{1} = vout_job(job);
    otherwise
        error('Unknown argument ("%s").', action);
end

%==========================================================================
% Run
%==========================================================================
function vout = run_job(job)

vout = vout_job(job);
tpm  = strvcat(cat(1,job.tissue(:).tpm));
tpm  = spm_load_priors8(tpm);

if ~isfield(job,'iterations'),   nit              =  1; else
                                 nit              = job.iterations; end
if ~isfield(job,'alpha'),        alpha            = 12; else
                                 alpha            = job.alpha;      end
if ~isfield(job.warp,'fwhm'),    job.warp.fwhm    =  1; end
if ~isfield(job.warp,'bb'),      job.warp.bb      =  NaN(2,3); end
if ~isfield(job.warp,'vox'),     job.warp.vox     =  NaN; end
if ~isfield(job.warp,'cleanup'), job.warp.cleanup =  0; end
if ~isfield(job.warp,'mrf'),     job.warp.mrf     =  0; end

if nit > 1
    orig_priors = tpm;
end

for iter=1:nit
    for subj=1:numel(job.channel(1).vols)
        fprintf('Segment %s\n',spm_file(job.channel(1).vols{subj},...
            'link','spm_image(''display'',''%s'')'));

        images = cell(numel(job.channel),1);
        for n=1:numel(job.channel)
            images{n} = job.channel(n).vols{subj};
        end
        obj.image    = spm_vol(char(images));
        spm_check_orientations(obj.image);

        obj.fwhm     = job.warp.fwhm;
        obj.biasreg  = cat(1,job.channel(:).biasreg);
        obj.biasfwhm = cat(1,job.channel(:).biasfwhm);
        obj.tpm      = tpm;
        obj.lkp      = [];
        if all(isfinite(cat(1,job.tissue.ngaus)))
            for k=1:numel(job.tissue)
                obj.lkp = [obj.lkp ones(1,job.tissue(k).ngaus)*k];
            end
        end
        obj.reg      = job.warp.reg;
        obj.samp     = job.warp.samp;

        if iter==1
            % Initial affine registration.
            Affine  = eye(4);
            if ~isempty(job.warp.affreg)
                if isfield(job.warp,'Affine')
                    Affine = job.warp.Affine;
                else
                    % Sometimes the image origins are poorly specified, in which case it might be worth trying
                    % the centre of the field of view instead. The idea here is to run a coarse registration
                    % using two sets of starting estimates, and pick the one producing the better objective function.

                    % Run using origin at centre of the field of view
                    im1            = obj.image(1);
                    M              = im1.mat;
                    c              = (im1.dim+1)/2;
                    im1.mat(1:3,4) = -M(1:3,1:3)*c(:);
                    [Affine1,ll1]  = spm_maff8(im1,8,(obj.fwhm+1)*16,tpm,[],job.warp.affreg); % Closer to rigid
                    Affine1        = Affine1*(im1.mat/M);

                    % Run using the origin from the header
                    im1            = obj.image(1);
                    [Affine2,ll2]  = spm_maff8(im1,8,(obj.fwhm+1)*16,tpm,[],job.warp.affreg); % Closer to rigid

                    % Pick the result with the best fit and use as starting estimate
                    if ll1>ll2
                        Affine  = Affine1;
                    else
                        Affine  = Affine2;
                    end
                end
                Affine = spm_maff8(obj.image(1),job.warp.samp,(obj.fwhm+1)*16,tpm,Affine,job.warp.affreg); % Closer to rigid
                Affine = spm_maff8(obj.image(1),job.warp.samp, obj.fwhm,      tpm,Affine,job.warp.affreg);
            end
            obj.Affine = Affine;
        else
            % Load results from previous iteration for use with next round of
            % iterations, with the new group-specific tissue probability map.
            [pth,nam] = fileparts(job.channel(1).vols{subj});
            res       = load(fullfile(pth,[nam '_seg8.mat']));
            obj.Affine = res.Affine;
            obj.Twarp  = res.Twarp;
            obj.Tbias  = res.Tbias;
            if ~isempty(obj.lkp)
                obj.mg     = res.mg;
                obj.mn     = res.mn;
                obj.vr     = res.vr;
            end
        end

        % in case masking is needed (e.g. CFM for lesions)
        if isfield(job,'msk')
            obj.msk = job.msk ;
        end

        res = spm_preproc8(obj);

        if ~isfield(job,'savemat') || job.savemat==1
            try
                [pth,nam] = fileparts(job.channel(1).vols{subj});
                save(fullfile(pth,[nam '_seg8.mat']),'-struct','res', spm_get_defaults('mat.format'));
            catch
            end
        end

        if iter==nit
            % Final iteration, so write out the required data.
            tmp1 = [cat(1,job.tissue(:).native) cat(1,job.tissue(:).warped)];
            tmp2 =  cat(1,job.channel(:).write);
            tmp3 = job.warp.write;
            spm_preproc_write8(res,tmp1,tmp2,tmp3,job.warp.mrf,job.warp.cleanup,job.warp.bb,job.warp.vox);
        else
            % Not the final iteration, so compute sufficient statistics for
            % re-estimating the template data.
            N    = numel(job.channel);
            K    = numel(job.tissue);
            [cls,M1] = spm_preproc_write8(res,zeros(K,4),zeros(N,2),[0 0],job.warp.mrf,...
                                          job.warp.cleanup,job.warp.bb,job.warp.vox);

            if subj==1
                % Sufficient statistics for possible generation of group-specific
                % template data.
                SS = zeros([size(cls{1}),numel(cls)],'single');
            end

            for k=1:K
                SS(:,:,:,k) = SS(:,:,:,k) + cls{k};
            end
        end

    end
    if iter<nit && nit>1
         % Treat the tissue probability maps as Dirichlet priors, and compute the
         % MAP estimate of group tissue probability map using the sufficient
         % statistics.
         [x1,x2] = ndgrid(1:size(SS,1),1:size(SS,2));
         for i=1:size(SS,3)
             M  = orig_priors.M\M1;
             y1 = M(1,1)*x1 + M(1,2)*x2 + M(1,3)*i + M(1,4);
             y2 = M(2,1)*x1 + M(2,2)*x2 + M(2,3)*i + M(2,4);
             y3 = M(3,1)*x1 + M(3,2)*x2 + M(3,3)*i + M(3,4);
             b  = spm_sample_priors8(orig_priors,y1,y2,y3);
             msk = (y1<1) | (y1>orig_priors.V(1).dim(1)) | ...
                   (y2<1) | (y2>orig_priors.V(1).dim(2)) | ...
                   (y3<1) | (y3>orig_priors.V(1).dim(3));
             for k=1:K
                 bk      = b{k}*alpha;
                 bk(msk) = bk(msk)*0.01;
                 SS(:,:,i,k) = SS(:,:,i,k) + bk;
             end
         end
         save SS.mat SS M1
         tpm.M = M1;
         s     = sum(SS,4);
         for k=1:K
             tmp        = SS(:,:,:,k)./s;
             tpm.bg1(k) = mean(mean(tmp(:,:,1)));
             tpm.bg2(k) = mean(mean(tmp(:,:,end)));
             tpm.dat{k} = spm_bsplinc(log(tmp+tpm.tiny),[ones(1,3)*(tpm.deg-1)  0 0 0]);
         end
    end
end

%==========================================================================
% Check
%==========================================================================
function msg = check_job(job)
msg = {};
if numel(job.channel) >1
    k = numel(job.channel(1).vols);
    for i=2:numel(job.channel)
        if numel(job.channel(i).vols)~=k
            msg = {['Incompatible number of images in channel ' num2str(i)]};
            break
        end
    end
elseif numel(job.channel)==0
    msg = {'No data'};
end

%==========================================================================
% Vout
%==========================================================================
function vout = vout_job(job)

n     = numel(job.channel(1).vols);
parts = cell(n,4);

channel = struct('biasfield',{},'biascorr',{});
for i=1:numel(job.channel)
    for j=1:n
        [parts{j,:}] = spm_fileparts(job.channel(i).vols{j});
    end
    if job.channel(i).write(1)
        channel(i).biasfield = cell(n,1);
        for j=1:n
            channel(i).biasfield{j} = fullfile(parts{j,1},['BiasField_',parts{j,2},'.nii']);
        end
    end
    if job.channel(i).write(2)
        channel(i).biascorr = cell(n,1);
        for j=1:n
            channel(i).biascorr{j} = fullfile(parts{j,1},['m',parts{j,2},'.nii']);
        end
    end
end

for j=1:n
    [parts{j,:}] = spm_fileparts(job.channel(1).vols{j});
end
param = cell(n,1);
for j=1:n
    param{j} = fullfile(parts{j,1},[parts{j,2},'_seg8.mat']);
end

tiss = struct('c',{},'rc',{},'wc',{},'mwc',{});
for i=1:numel(job.tissue)
    if job.tissue(i).native(1)
        tiss(i).c = cell(n,1);
        for j=1:n
            tiss(i).c{j} = fullfile(parts{j,1},['c',num2str(i),parts{j,2},'.nii']);
        end
    end
    if job.tissue(i).native(2)
        tiss(i).rc = cell(n,1);
        for j=1:n
            tiss(i).rc{j} = fullfile(parts{j,1},['rc',num2str(i),parts{j,2},'.nii']);
        end
    end
    if job.tissue(i).warped(1)
        tiss(i).wc = cell(n,1);
        for j=1:n
            tiss(i).wc{j} = fullfile(parts{j,1},['wc',num2str(i),parts{j,2},'.nii']);
        end
    end
    if job.tissue(i).warped(2)
        tiss(i).mwc = cell(n,1);
        for j=1:n
            tiss(i).mwc{j} = fullfile(parts{j,1},['mwc',num2str(i),parts{j,2},'.nii']);
        end
    end
end

if job.warp.write(1)
    invdef = cell(n,1);
    for j=1:n
        invdef{j} = fullfile(parts{j,1},['iy_',parts{j,2},'.nii']);
    end
else
    invdef = {};
end

if job.warp.write(2)
    fordef = cell(n,1);
    for j=1:n
        fordef{j} = fullfile(parts{j,1},['y_',parts{j,2},'.nii']);
    end
else
    fordef = {};
end

vout  = struct('channel',channel,'tiss',tiss,'param',{param},'invdef',{invdef},'fordef',{fordef});

%==========================================================================
% Vfiles
%==========================================================================
function vf = vfiles_job(job)
vout = vout_job(job);
vf   = vout.param;
if ~isempty(vout.invdef), vf = {vf{:}, vout.invdef{:}}; end
if ~isempty(vout.fordef), vf = {vf{:}, vout.fordef{:}}; end
for i=1:numel(vout.channel)
    if ~isempty(vout.channel(i).biasfield), vf = {vf{:}, vout.channel(i).biasfield{:}}; end
    if ~isempty(vout.channel(i).biascorr),  vf = {vf{:}, vout.channel(i).biascorr{:}};  end
end

for i=1:numel(vout.tiss)
    if ~isempty(vout.tiss(i).c),   vf = {vf{:}, vout.tiss(i).c{:}};   end
    if ~isempty(vout.tiss(i).rc),  vf = {vf{:}, vout.tiss(i).rc{:}};  end
    if ~isempty(vout.tiss(i).wc),  vf = {vf{:}, vout.tiss(i).wc{:}};  end
    if ~isempty(vout.tiss(i).mwc), vf = {vf{:}, vout.tiss(i).mwc{:}}; end
end
vf = reshape(vf,numel(vf),1);


function varargout = process_cohere1( varargin )
% PROCESS_COHERE1: Compute the coherence between one signal and all the others, in one file.
%
% USAGE:  OutputFiles = process_cohere1('Run', sProcess, sInputA)
%                       process_cohere1('Test', 1)
%                       process_cohere1('Test', 2)

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

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Coherence 1xN [Deprecated]';
    sProcess.Category    = 'Custom';
    sProcess.SubGroup    = 'Connectivity';
    sProcess.Index       = 655;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/Connectivity';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data',     'results',  'matrix'};
    sProcess.OutputTypes = {'timefreq', 'timefreq', 'timefreq'};
    sProcess.nInputs     = 1;
    sProcess.nMinFiles   = 1;

    % === CONNECT INPUT
    sProcess = process_corr1n('DefineConnectOptions', sProcess, 0);
    % === REMOVE EVOKED REPONSE
    sProcess.options.removeevoked.Comment = 'Remove evoked response from each trial';
    sProcess.options.removeevoked.Type    = 'checkbox';
    sProcess.options.removeevoked.Value   = 0;
    sProcess.options.removeevoked.Group   = 'input';
    % === COHERENCE METHOD
    sProcess.options.cohmeasure.Comment = {...
        ['Magnitude-squared Coherence
' ...
        '|C|^2 = |Gxy|^2/(Gxx*Gyy)'], ...
        ['Imaginary Coherence (2019)
' ...
        'IC    = |imag(C)|'], ...
        ['Lagged Coherence (2019)
' ...
        'LC    = |imag(C)|/sqrt(1-real(C)^2)'], ...
        [' Imaginary Coherence (before 2019)
' ...
        ' IC    = imag(C)^2 / (1-real(C)^2) ']; ...
        'mscohere', 'icohere2019','lcohere2019', 'icohere'};
    sProcess.options.cohmeasure.Type    = 'radio_label';
    sProcess.options.cohmeasure.Value   = 'mscohere';
    % === Overlap
    sProcess.options.overlap.Comment = 'Overlap for PSD estimation:' ;
    sProcess.options.overlap.Type    = 'value';
    sProcess.options.overlap.Value   = {50, '%', []};
    % === MAX FREQUENCY RESOLUTION
    sProcess.options.maxfreqres.Comment = 'Maximum frequency resolution:';
    sProcess.options.maxfreqres.Type    = 'value';
    sProcess.options.maxfreqres.Value   = {2,'Hz',2};
    % === HIGHEST FREQUENCY OF INTEREST
    sProcess.options.maxfreq.Comment = 'Highest frequency of interest:';
    sProcess.options.maxfreq.Type    = 'value';
    sProcess.options.maxfreq.Value   = {60,'Hz',2};
    % === OUTPUT MODE
    sProcess.options.outputmode.Comment = {'Save individual results (one file per input file)', 'Concatenate input files before processing (one file)', 'Save average connectivity matrix (one file)'};
    sProcess.options.outputmode.Type    = 'radio';
    sProcess.options.outputmode.Value   = 1;
    sProcess.options.outputmode.Group   = 'output';
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    Comment = sProcess.Comment;
end

%% ===== RUN =====
function OutputFiles = Run(sProcess, sInputA) %#ok<DEFNU>
    % Input options
    OPTIONS = process_corr1n('GetConnectOptions', sProcess, sInputA);
    if isempty(OPTIONS)
        OutputFiles = {};
        return
    end

    % Metric options
    OPTIONS.Method = 'cohere';
    OPTIONS.RemoveEvoked  = sProcess.options.removeevoked.Value;
    OPTIONS.MaxFreqRes    = sProcess.options.maxfreqres.Value{1};
    OPTIONS.MaxFreq       = sProcess.options.maxfreq.Value{1};
    OPTIONS.CohOverlap    = 0.50;  % First pre-define the overlap
    OPTIONS.pThresh       = 0.05;
    OPTIONS.CohMeasure    = sProcess.options.cohmeasure.Value;

    % Change the overlap if it is specified
    if isfield(sProcess.options, 'overlap') && isfield(sProcess.options.overlap, 'Value') && ...
       iscell(sProcess.options.overlap.Value) && ~isempty(sProcess.options.overlap.Value) && ~isempty(sProcess.options.overlap.Value{1})
        OPTIONS.CohOverlap = sProcess.options.overlap.Value{1}/100 ;
    end

    % Compute metric
    OutputFiles = bst_connectivity({sInputA.FileName}, {sInputA.FileName}, OPTIONS);
end

%% ===== TEST FUNCTION =====
function Test(iTest) %#ok<DEFNU>
    % Start a new report
    bst_report('Start');
    % Select tests
    if (nargin < 1) || isempty(iTest)
        iTest = 1;
    end
    % Get test datasets
    switch iTest
        case 1,  sFile = process_simulate_matrix('Test');
        case 2,  sFile = process_simulate_ar('Test');
    end
    % Loop on frequency resolutions
    for freq = [1 2 3 5 10 20]
        % Coherence process
        sTmp = bst_process('CallProcess', 'process_cohere1', sFile, [], ...
            'timewindow',   [], ...    % All the time in input
            'src_rowname',  '1', ...   % Test signal #1 => other signals
            'cohmeasure',   1, ...     % 1=Magnitude-squared, 2=Imaginary
            'overlap',      3, ...     % 50%
            'maxfreqres',   freq, ...  % VARIES
            'maxfreq',      [], ...    % No maximum frequency
            'pThresh',      0.05, ...  % p-value thrshold
            'outputmode',   1);        % Save individual results (one file per input file)
        % Snapshot: spectrum
        bst_process('CallProcess', 'process_snapshot', sTmp, [], ...
            'target',       10, ...  % Frequency spectrum
            'modality',     1, 'orient', 1, 'time', 0, 'contact_time', [-40, 110], 'contact_nimage', 16, ...
            'Comment',      [sFile.Comment, ': ' sTmp.Comment]);
    end
    % Save and display report
    ReportFile = bst_report('Save', sFile);
    bst_report('Open', ReportFile);
end


%VAR Dataset overload
%
%   [V,U] = VAR(A,W)
%
% Computes variance V and mean U in a single run for consistency with datafile overload.


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

%%
clear; close all; clc;

%% Syntax
% |[domNode]=febioStruct2xml(febio_spec,fileName,optionStruct);|

%% Description
% This function provides the basis for coding FEBio XML input file content
% and helps to generate the XML input file.

%%
% See also: |febioStructTemplate|

%% About FEBio XML input files
% FEBio input files (.feb) are XML files. The XML syntax bellow is for
% febio_spec 2.5. More on the input file formatting can be found in the
% FEBio user manual.

%% Coding XML files in MATLAB
% Coding XML files (or in this case .feb FEBio files) can be challenging
% and may look confusing. An alternative method is implemented here which
% is a trade-off between clarify, ease of programming, and fidelity with
% the generated XML file. In general XML files follow the following form:

%%

% <Globals>
%   <Constants>
%       <R>8.314e-6</R>
%       <T>298</T>
%       <Fc>96485e-9</Fc>
%   </Constants>
%   <Solutes>
%       <solute id="1" name="Na">
%           <charge_number>1</charge_number>
%           <molar_mass>22.99</molar_mass>
%           <density>0.97<density>
%       </solute>
% </Globals>

%%
% Here Globals is an element with the entries Constants and Solutes being
% child elements (and Constants and Solutes have R,T,Fc and solute as their
% respective child elements,... etc). The symbols <..> start an element and
% </..> closes that element. Components within <..> sometimes contain
% attributes. An example of this is id="1", here the attribute "id" has the
% value "1" associated with it, another example of an attribute is
% name="Na". Elements may contain child elements and may have a value. For
% instance the element Constants has children but the element R has the
% value 8.314e-6 associated with it.
% To code these features in MATLAB a particular syntax was developed.
% Structures are suitable as they are tree-like similar to XML. However
% structures lack the attribute feature, i.e. fields in structures have
% values but do not have attributes associated with them. To solve this
% keywords are used here to denote attributes and to distinguish them from
% values or elements. For instance node.ATTR.id=1 will become <node
% id="1">, where the ATTR keyword is here simply used as a target/trigger
% keyword for determining wheter the subsequent feature is an element,
% value or attribute. Futhermore the VAL keyword exists to denote a value,
% e.g. node.ATTR.id=1; node.VAL=2;  will become: <node id="1"> 2 </node>.

%%
% One may use arrays for values as well i.e. node.ATTR.id=nodeIdArray;
% node.VAL=nodeCoordinateArray; can be used to define sets of attributes
% and sets of values simultaneously.
%%
% In principle all FEBio functionality (based on XML content) can be coded
% for in a similar fashion. Study the FEBio user manual for more
% information.

%%
% The remainder of this documentation will describe how various XML
% components of the FEBio input file can be coded. A structure is created
% with the name "febio_spec". For more information on coding the febio
% structure see the various FEBio demos provided.

%% Set febio_spec version
febio_spec.ATTR.version='3.0';

%% Module section
% XML syntax example:
% <Module type="Solid"/>

%%
% Implementation example
febio_spec.Module.ATTR.type='solid';

%% Control section

%% Example 1: Globals section

% <Globals>
%   <Constants>
%       <R>8.314e-6</R>
%       <T>298</T>
%       <Fc>96485e-9</Fc>
%   </Constants>
%   <Solutes>
%       <solute id="1" name="Na">
%           <charge_number>1</charge_number>
%           <molar_mass>22.99</molar_mass>
%           <density>0.97<density>
%       </solute>
%       <solute id="2" name="Cl">
%           <charge_number>-1</charge_number>
%           <molar_mass>35.45</molar_mass>
%           <density>3.21<density>
%       </solute>
%       <solute id="3" name="Glc">
%           <charge_number>0</charge_number>
%           <molar_mass>180.16</molar_mass>
%           <density>1.54<density>
%       </solute>
%   </Solutes>
% </Globals>

febio_spec.Globals.Constants.T=0;
febio_spec.Globals.Constants.R=0;
febio_spec.Globals.Constants.Fc=0;

febio_spec.Globals.Solutes{1}.ATTR.id=1;
febio_spec.Globals.Solutes{1}.ATTR.name='Na';
febio_spec.Globals.Solutes{1}.charge_number=1;
febio_spec.Globals.Solutes{1}.molar_mass=22.99;
febio_spec.Globals.Solutes{1}.density=0.97;

febio_spec.Globals.Solutes{2}.ATTR.id=2;
febio_spec.Globals.Solutes{2}.ATTR.name='Cl';
febio_spec.Globals.Solutes{2}.charge_number=-1;
febio_spec.Globals.Solutes{2}.molar_mass=35.45;
febio_spec.Globals.Solutes{2}.density=3.21;

%% Example 2: Material section

%%
% An uncouple material
febio_spec.Material.material{1}.ATTR.type='Ogden';
febio_spec.Material.material{1}.ATTR.id=1;
febio_spec.Material.material{1}.c1=1;
febio_spec.Material.material{1}.m1=6;
febio_spec.Material.material{1}.k=100;

%%
% A visco-elastic material

%Viscoelastic part
febio_spec.Material.material{2}.ATTR.type='uncoupled viscoelastic';
febio_spec.Material.material{2}.ATTR.Name='Block_material';
febio_spec.Material.material{2}.ATTR.id=2;
febio_spec.Material.material{2}.g1=0.1;
febio_spec.Material.material{2}.t1=0.01;
febio_spec.Material.material{2}.density=1e-9;

%Elastic part
febio_spec.Material.material{2}.elastic{1}.ATTR.type='Ogden';
febio_spec.Material.material{2}.elastic{1}.c1=1;
febio_spec.Material.material{2}.elastic{1}.m1=2;
febio_spec.Material.material{2}.elastic{1}.k=100;
febio_spec.Material.material{2}.elastic{1}.density=1e-9;

%%
% A poro-elastic material

%Viscous part
febio_spec.Material.material{3}.ATTR.type='biphasic';
febio_spec.Material.material{3}.ATTR.name='Block_material';
febio_spec.Material.material{3}.ATTR.id=3;
febio_spec.Material.material{3}.phi0=0.5;
febio_spec.Material.material{3}.permeability.ATTR.type='perm-const-iso';
febio_spec.Material.material{3}.permeability.ATTR.name='permeability';
febio_spec.Material.material{3}.permeability.perm=7.41e-11; %hydraulic permeability
febio_spec.Material.material{3}.fluid_density=1e-9;

%Solid part
febio_spec.Material.material{3}.solid{1}.ATTR.type='Ogden unconstrained';
febio_spec.Material.material{3}.solid{1}.c1=1;
febio_spec.Material.material{3}.solid{1}.m1=2;
febio_spec.Material.material{3}.solid{1}.cp=100;
febio_spec.Material.material{3}.solid{1}.density=1e-9;

%%
% A poro-elastic and visco-elastic material

% 	<Material>
% 		<material id="1" name="Biphasic-Viscoelastic" type="biphasic">
% 			<phi0>0.2</phi0>
% 			<solid type="viscoelastic">
% 				<g1>0.5</g1>
% 				<t1>3000</t1>
% 				<elastic type="solid mixture">
% 					<solid type="neo-Hookean">
% 						<density>1</density>
% 						<E>0.5</E>
% 						<v>0</v>
% 					</solid>
% 					<solid type="ellipsoidal fiber distribution">
% 						<beta>2,2,2</beta>
% 						<ksi>5,5,5</ksi>
% 					</solid>
% 				</elastic>
% 			</solid>
% 			<permeability type="perm-Holmes-Mow">
% 				<perm>0.001</perm>
% 				<M>3</M>
% 				<alpha>2</alpha>
% 			</permeability>
% 		</material>

%Viscous part
febio_spec.Material.material{4}.ATTR.type='biphasic';
febio_spec.Material.material{4}.ATTR.name='Biphasic-Viscoelastic';
febio_spec.Material.material{4}.ATTR.id=4;
febio_spec.Material.material{4}.phi0=0.2;
febio_spec.Material.material{4}.permeability.ATTR.type='perm-Holmes-Mow';
febio_spec.Material.material{4}.permeability.perm=0.001;
febio_spec.Material.material{4}.permeability.M=3;
febio_spec.Material.material{4}.permeability.alpha=2;

%Solid part
%-> Viscoelastic part
febio_spec.Material.material{4}.solid{1}.ATTR.type='viscoelastic';
febio_spec.Material.material{4}.solid{1}.g1=0.5;
febio_spec.Material.material{4}.solid{1}.t1=3000;
febio_spec.Material.material{4}.solid{1}.density=1e-9;

%-> Elastic part
febio_spec.Material.material{4}.solid{1}.elastic{1}.ATTR.type='solid mixture';
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{1}.ATTR.type='neo-Hookean';
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{1}.density=1e-9;
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{1}.E=0.5;
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{1}.v=0;
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{2}.ATTR.type='ellipsoidal fiber distribution';
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{2}.beta=[2 2 2];
febio_spec.Material.material{4}.solid{1}.elastic{1}.solid{2}.ksi=[5 5 5];

%% Example 3: Mesh section

%Example geometry
[meshStruct]=hexMeshBox([2 2 2],[2 2 2]);
E=meshStruct.E; V=meshStruct.V;
bcSupportList=(1:size(V,1))';

% -> Nodes

% <Nodes name="Object1">
%   <node id="1">0,0,0,</node>
%   <node id="2">1,0,0,</node>
%   ...
% </Nodes>

febio_spec.Mesh.Nodes{1}.ATTR.name='Object1'; %The node set name
febio_spec.Mesh.Nodes{1}.node.ATTR.id=(1:size(V,1))'; %The node id's
febio_spec.Mesh.Nodes{1}.node.VAL=V; %The nodel coordinates

% -> Elements

% <Elements type="hex8" name="Part1">
%   <elem id="1">1,2,3,4,5,6,7,8</elem>
%   <elem id="2">1,2,3,4,9,10,11,12</elem>
%   <...>
% </Elements>

partName1='Part1';
febio_spec.Mesh.Elements{1}.ATTR.name=partName1; %Name of this part
febio_spec.Mesh.Elements{1}.ATTR.type='hex8'; %Element type
febio_spec.Mesh.Elements{1}.elem.ATTR.id=(1:1:size(E,1))'; %Element id's
febio_spec.Mesh.Elements{1}.elem.VAL=E; %The element matrix

% -> NodeSets
nodeSetName1='bcSupportList';
febio_spec.Mesh.NodeSet{1}.ATTR.name=nodeSetName1;
febio_spec.Mesh.NodeSet{1}.node.ATTR.id=bcSupportList(:);

%% Creating the FEBio input file
% You can use |febioStruct2xml| to write the xml data to a file AND/OR a
% domNode object (optional output). Leave the fileName variable empty to
% supress file export.

%Create file name for XML file
defaultFolder = fileparts(fileparts(mfilename('fullpath')));
savePath=fullfile(defaultFolder,'data','temp');
fileName=fullfile(savePath,'tempModel.feb');

optionStruct.arrayParseMethod=1;
[domNode]=febioStruct2xml(febio_spec,fileName,optionStruct);

%% Viewing the FEBio input file
% The |febView| command can be used to render an XML file in a figure
% window. Alternatively the |textView| command can be used:
h=febView(fileName,2);

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

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


classdef AnalysisMagnitudeHist < HistAnalysisWindow
    methods
        function obj=AnalysisMagnitudeHist(ax)
            obj@HistAnalysisWindow(ax);
        end

        function prepare_axes(obj)
            % prepare the cumulative event rate axes
            if isempty(obj.ax.Tag)
                obj.ax.Tag = 'dvCumrate';
            end
            obj.ax.Title.String='Cumulative Rate';
            obj.ax.XLabel.String='Time';
            obj.ax.YLabel.String='Cumulative Events';
        end

        function [x,y]=calculate(obj,catalog)
            % calculate the cumulative number of events (y) over time (x)
            x=sort(catalog.Date);
            y=[]; % histogram?
        end

    end
end


function bytestream=savenifti(img, filename, varargin)
%
%    savenifti(img, filename)
%        or
%    savenifti(img, filename, rawhdr)
%    savenifti(img, filename, 'nifti2')
%    bytestream=savenifti(img)
%
%    Write an image to a NIfTI (*.nii) or compressed NIfTI file (.nii.gz)
%
%    author: Qianqian Fang (q.fang <at> neu.edu)
%
%    input:
%        img: this is a numerical array to be stored in the NIfTI file
%        filename: output file name, can have a suffix of '.nii' or '.nii.gz'
%                 if a .gz suffix is used, this function needs the JSONLab
%                 (http://gitlab.com/fangq/jsonlab) and ZMat (http://gitlab.com/fangq/zmat)
%                 to perform the compression.
%        rawhdr (optional): a struct, as a pre-created/loaded NIfTI header data structure
%                if rawhdr is 'nifti1' or 'nifti2', this function calls
%                nifticreate to create a default header.
%    output:
%        bytestream (optional): the output file byte stream. it only returns this output if
%                no filename is given.
%
%    example:
%        a=single(rand(10,20,30));
%        savenifti(a,'randnii.nii');
%        savenifti(a,'randnii2.nii.gz','nifti2'); % needs zmat
%
%
%    this file is part of JNIfTI specification: https://github.com/fangq/jnifti
%
%    License: Apache 2.0, see https://github.com/fangq/jnifti for details
%

if(~isempty(varargin))
    if(isstruct(varargin{1}))
        header=varargin{1};
    elseif(ischar(varargin{1}))
        header=nifticreate(img,varargin{1});
    end
else
    header=nifticreate(img);
end

names=fieldnames(header);
buf=[];
for i=1:length(names)
    buf=[buf,typecast(header.(names{i}),'uint8')];
end

if(length(buf)~=352 && length(buf)~=544)
    error('incorrect nifti-1/2 header %d',length(buf));
end

buf=[buf,typecast(img(:)','uint8')];

if(nargout>1 && nargin<2)
    bytestream=buf;
    return;
end

if(regexp(filename,'\.[Gg][Zz]$'))
    buf=gzipencode(buf);
end

fid=fopen(filename,'wb');
if(fid==0)
    error('can not write to the specified file');
end
fwrite(fid,buf);
fclose(fid);


function drawSeg(h,x,c)

% DRAWSEG  Draw 2D or 3D segment with color.
%   DRAWSEG(H,S) Draws 2D or 3D segment S=[p1;p2] with handle H.
%
%   DRAWSEG(H,S,C) uses color C.

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

if numel(x) == 4

    set(h,'xdata',x([1 3]),'ydata',x([2 4]),'vis','on')

elseif numel(x) == 6

    set(h,'xdata',x([1 4]),'ydata',x([2 5]),'zdata',x([3 6]),'vis','on')

else

    error('??? Size of vector ''x'' not correct.')

end

if nargin == 3
    set(h,'color',c)
end

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB is free software: you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation, either version 3 of the License, or
%   (at your option) any later version.
%
%   SLAMTB is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You should have received a copy of the GNU General Public License
%   along with SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE