function varargout = sp_gen(varargin)
%
%
% sp_gen is a GUI for generating Spirals.
%
%A. Select the plane that will be parallel to the spiral
%B. Select the type of spiral:
%You can choose from Archimedean,Logarithmic,Fermat,Hyperbolic,Lituus,Spherical and Polynomial Spirals.
%you can see the equations used for the selected spiral, and change the parameters.
%C. Select the normal component of the spiral. Note that this feature is
%not available for the spherical spirals.
%D. Add thickness to the spiral. This will provide volume and will give you
%the possibility to generate surfaces. Note that this feature is not
%available for the polynomial spirals.
%E. Generate and export spiral variables to the workspace.
%
%%%%%%BUGS
%
%I am aware of the surface bug. This is clearly visible in the spherical
%spiral, but also in the other spirals if you play with the normal
%component.This is caused because the surface twists around itself. I
%provide a partial correction, in function 'generate_thickness' in the 'if'
%statement in lines 1128-1130.
%
% If anybody comes with a solution to this or finds other bugs, please post
% on File EXchange.
%
%
%Created by Katelouzos Ioannis.

gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @sp_gen_OpeningFcn, ...
                   'gui_OutputFcn',  @sp_gen_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 sp_gen is made visible.
function sp_gen_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 sp_gen (see VARARGIN)

% Choose default command line output for sp_gen
handles.output = hObject;
handles.plane=[0 0 1];
vr=[[1 0;-1 0;0 1;0 -1]*null([0 0 1])';0 0 0];
fc=[1 5 3;2 5 3;2 5 4;1 4 5];
fv.vertices=vr;
fv.faces=fc;
handles.fv=fv;
handles.xpl=zeros(3,3);
handles.ypl=zeros(3,3);
handles.zpl=zeros(3,3);
handles.surface=0;
handles.scloud=0;
handles.cloud=0;
handles.cerchi=[0;0;0];
handles.oct=zeros(8,3);
handles.spiral=zeros(3,1);
% Update handles structure
guidata(hObject, handles);

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

% --- Outputs from this function are returned to the command line.
function varargout = sp_gen_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 selection change in spiral_type.
function spiral_type_Callback(hObject, eventdata, handles)
% hObject    handle to spiral_type (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
val=(get(hObject,'Value'));
zz=(get(handles.zcomp,'Value'));
switch val
    case 1
        set(handles.text15,'String','r = a + b * theta');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 2
        set(handles.text15,'String','r = a * exp( b * theta )');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 3
        set(handles.text15,'String','r = +- sqrt( theta )');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','off');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 4
        set(handles.text15,'String','r = a / theta');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 5
        set(handles.text15,'String','r = sqrt( 1 / theta )');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','off');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 6
        set(handles.text15,'String','x=cos(t)cos(c) y=sin(t)cos(c)  z=-sin(c) c=atan(a*t)');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','off');
        set(handles.c,'Enable','off');
        set(handles.d,'Enable','off');
        set(handles.e,'Enable','off');
        set(handles.f,'Enable','off');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
    otherwise
        set(handles.text15,'String','curvature = f(curve length) k=a*s^4+b*s^3+g*s^2+h*s+i');
        set(handles.g,'Enable','on');
        set(handles.h,'Enable','on');
        set(handles.i,'Enable','on');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','off');
        set(handles.surfface,'Enable','off');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
        end

end
guidata(hObject, handles);
% Hints: contents = get(hObject,'String') returns spiral_type contents as cell array
%        contents{get(hObject,'Value')} returns selected item from spiral_type

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

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

function Xeq_Callback(hObject, eventdata, handles)
% hObject    handle to Xeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
pl=handles.plane;
x=str2double(get(hObject,'String'));
if pl(3)==0 && pl(2)==0, x=1;
set(hObject,'String','1');
end
handles.plane(1)=x;
handles=refresh_plane(handles);
guidata(hObject, handles);
% Hints: get(hObject,'String') returns contents of Xeq as text
%        str2double(get(hObject,'String')) returns contents of Xeq as a double

% --- Executes during object creation, after setting all properties.
function Xeq_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Xeq (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.
handles.plane(1)=str2double(get(hObject,'String'));
guidata(hObject, handles);
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Yeq_Callback(hObject, eventdata, handles)
% hObject    handle to Yeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
pl=handles.plane;
x=str2double(get(hObject,'String'));
if pl(1)==0 && pl(3)==0, x=1;
set(hObject,'String','1');
end
handles.plane(2)=x;
handles=refresh_plane(handles);
guidata(hObject, handles);
% Hints: get(hObject,'String') returns contents of Yeq as text
%        str2double(get(hObject,'String')) returns contents of Yeq as a double

% --- Executes during object creation, after setting all properties.
function Yeq_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Yeq (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.
handles.plane(2)=str2double(get(hObject,'String'));
guidata(hObject, handles);
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Zeq_Callback(hObject, eventdata, handles)
% hObject    handle to Zeq (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 Zeq as text
%        str2double(get(hObject,'String')) returns contents of Zeq as a double
pl=handles.plane;
x=str2double(get(hObject,'String'));
if pl(1)==0 && pl(2)==0, x=1;
set(hObject,'String','1');
end
handles.plane(3)=x;
handles=refresh_plane(handles);
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function Zeq_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Zeq (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.
handles.plane(3)=str2double(get(hObject,'String'));
guidata(hObject, handles);
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in show_plane.
function show_plane_Callback(hObject, eventdata, handles)
% hObject    handle to show_plane (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles=refresh_plane(handles);
guidata(hObject, handles);
% Hint: get(hObject,'Value') returns toggle state of show_plane

function thick_Callback(hObject, eventdata, handles)
% hObject    handle to thick (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
x=str2double(get(hObject,'String'));
if x<0;
set(hObject,'String','0');
end
guidata(hObject, handles);
% Hints: get(hObject,'String') returns contents of thick as text
%        str2double(get(hObject,'String')) returns contents of thick as a double

% --- Executes during object creation, after setting all properties.
function thick_CreateFcn(hObject, eventdata, handles)
% hObject    handle to thick (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function lengt_Callback(hObject, eventdata, handles)
% hObject    handle to lengt (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 lengt as text
%        str2double(get(hObject,'String')) returns contents of lengt as a double

x=str2double(get(hObject,'String'));
pr=str2double(get(handles.precision,'String'));
if x<=2*pr;
pr=str2double(get(handles.precision,'String'));
set(hObject,'String',sprintf('%g', pr*2));
end
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function lengt_CreateFcn(hObject, eventdata, handles)
% hObject    handle to lengt (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function h=refresh_plane(handles)
cpos=get(handles.axes1,'CameraPosition');
pl=handles.plane;
 vr=[[1 0;-1 0;0 1;0 -1;1 1; 1 -1;-1 -1;-1 1]*null(pl)';0 0 0];
fv.vertices=vr;
xpl=[vr(8,1) vr(3,1) vr(5,1);vr(2,1) vr(9,1) vr(1,1);vr(7,1) vr(4,1) vr(6,1)];
ypl=[vr(8,2) vr(3,2) vr(5,2);vr(2,2) vr(9,2) vr(1,2);vr(7,2) vr(4,2) vr(6,2)];
zpl=[vr(8,3) vr(3,3) vr(5,3);vr(2,3) vr(9,3) vr(1,3);vr(7,3) vr(4,3) vr(6,3)];
handles.xpl=xpl;
handles.ypl=ypl;
handles.zpl=zpl;
spir=handles.spiral;

if isempty(find(spir));
    mm=1;
else mm=max(max(abs(spir)));
end
xpl=xpl.*mm/2;
ypl=ypl.*mm/2;
zpl=zpl.*mm/2;
plot3(spir(1,:),spir(2,:),spir(3,:));
hold on;
if get(handles.show_plane,'Value')==1
    mesh(xpl,ypl,zpl,'FaceAlpha',0.1,'FaceColor','g','EdgeAlpha',0.5,'EdgeColor','k');
end
set(handles.axes1,'CameraPosition',cpos);
set(handles.axes1,'DataAspectRatio',[1 1 1]);
set(get(handles.axes1,'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(handles.axes1,'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(handles.axes1,'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
h=handles;

% --- Executes on button press in export_internal.
function export_internal_Callback(hObject, eventdata, handles)
% hObject    handle to export_internal (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cloud=handles.cloud;
assignin('base','Spiral_IntCloud',cloud);

% --- Executes on button press in show_scloud.
function show_scloud_Callback(hObject, eventdata, handles)
% hObject    handle to show_scloud (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.export_scloud,'BackgroundColor',[0 1 0]);
set(handles.export_scloud,'Enable','on');
H=figure(2);
title('Surface Cloud Ordinary','Color','b','FontWeight','bold');
oct=handles.oct;
hold on;
for it=1:length(oct(1,1,:))
    plot3(oct(:,1,it),oct(:,2,it),oct(:,3,it),'.');
end
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
H=figure(3);
title('Surface Cloud Random','Color','b','FontWeight','bold');
scloud=gen_scloud(handles,oct);
handles.scloud=scloud;
hold on;
plot3(scloud(:,1),scloud(:,2),scloud(:,3),'.');
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
guidata(hObject, handles);

% --- Executes on button press in show_surface.
function show_surface_Callback(hObject, eventdata, handles)
% hObject    handle to show_surface (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.export_surface,'BackgroundColor',[0 1 0]);
set(handles.export_surface,'Enable','on');
H=figure(4);

oct=handles.oct;
C = permute(cat(1, oct, oct(1,:,:)),[3,1,2]);
xsurf=squeeze(C(:,:,1));
ysurf=squeeze(C(:,:,2));
zsurf=squeeze(C(:,:,3));
surface.x=xsurf;
surface.y=ysurf;
surface.z=zsurf;
handles.surface=surface;
mesh(xsurf,ysurf,zsurf,'FaceAlpha',0.1,'FaceColor','g','EdgeAlpha',0.5,'EdgeColor','k');
title('Surface','Color','b','FontWeight','bold');
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
guidata(hObject, handles);

% --- Executes on button press in show_internal.
function show_internal_Callback(hObject, eventdata, handles)
% hObject    handle to show_internal (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.export_internal,'BackgroundColor',[0 1 0]);
set(handles.export_internal,'Enable','on');
H=figure(1);
title('Internal Cloud','Color','b','FontWeight','bold');
oct=handles.oct;

cloud=gen_cloud(handles,oct);
handles.cloud=cloud;
hold on;
plot3(cloud(:,1),cloud(:,2),cloud(:,3),'.');
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
guidata(hObject, handles);

% --- Executes on button press in export_scloud.
function export_scloud_Callback(hObject, eventdata, handles)
% hObject    handle to export_scloud (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
oct=handles.oct;
scloud=handles.scloud;
B = permute(oct,[1 3 2]);
ou = reshape(B,length(oct(:,1,1))*size(oct,3),3);
assignin('base','Spiral_SurCloud_ord',ou);
assignin('base','Spiral_SurCloud_rand',scloud);

% --- Executes on button press in export_surface.
function export_surface_Callback(hObject, eventdata, handles)
% hObject    handle to export_surface (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
surface=handles.surface;
assignin('base','Spiral_Surface',surface);

% --- Executes on button press in export_line.
function export_line_Callback(hObject, eventdata, handles)
% hObject    handle to export_line (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
assignin('base','Spiral_line',handles.spiral);

% --- Executes on button press in gen_spiral.
function gen_spiral_Callback(hObject, eventdata, handles)
% hObject    handle to gen_spiral (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cpos=get(handles.axes1,'CameraPosition');
stype=get(handles.spiral_type,'Value');
alpha=str2double(get(handles.alpha,'String'));
beta=str2double(get(handles.beta,'String'));
c=str2double(get(handles.c,'String'));
d=str2double(get(handles.d,'String'));
e=str2double(get(handles.e,'String'));
f=str2double(get(handles.f,'String'));
g=str2double(get(handles.g,'String'));
h=str2double(get(handles.h,'String'));
i=str2double(get(handles.i,'String'));
thick=str2double(get(handles.thick,'String'));
pr=str2double(get(handles.precision,'String'));
lengt=str2double(get(handles.lengt,'String'));
theta=0:pr:lengt*pi;
switch stype
    case 1
        r=alpha+beta*theta;
    case 2
        r=alpha*(exp(beta*theta));
    case 3
        r=sqrt(theta);
        r2=-r;
    case 4
        r=alpha./theta;
    case 5
        r=sqrt(1./theta);
    case 6
        t=-lengt:pr:lengt;
        c=atan(alpha*t);
        x=cos(t).*cos(c);
        y=sin(t).*cos(c);
        z=-sin(c);
        [theta,r]=cart2pol(x,y);
    otherwise
        if alpha>0
            l=sqrt(lengt);
            p=pr^2;
        else
            l=lengt;
            p=pr;
        end
        [x y]=curv2cart(alpha,beta,g,h,i,l,p,handles);
        [theta,r]=cart2pol(x,y);
end
zc=(get(handles.zcomp,'Value'));
if stype~=6
switch zc
    case 1
        z=zeros(1,length(theta));
    case 2
        z=c*r.^d+e*theta.^f;
    case 3
        z = c*sin(r.*d) + e*sin(theta.*f);
    case 4
        z = c*exp(d*r) + e*exp(f*theta);
    otherwise
        z = c*log(r).^d + e*log(theta).^f;
end
end
if stype==4 || stype==5
    theta=theta(end:-1:2);
    r=r(end:-1:2);
    z=z(end:-1:2);
end
[x,y]=pol2cart(theta,r);
spiral=[x;y;z];
if stype==3
    [x2,y2]=pol2cart(theta,r2);
    z2=-z;
    spiral=[fliplr(x2) x(2:end);fliplr(y2) y(2:end);fliplr(z2) z(2:end)];
end
pl=handles.plane;
rotate= vrrotvec([0 0 1],pl);
rm = vrrotvec2mat(rotate);
spir=rm*spiral;
nnn=sum(spir,1);
w=nnn==nnn;
w=find(w==0);
spir(:,w)=[];
handles.spiral=spir;
if ~isempty(find(spir))
    refresh_plane(handles);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   cerchiles generation
hold on;
if thick>0
    if stype==1 || stype==2 || stype ==6 ||stype==4 ||stype==5
        [cerchi oct]=generate_thickness(1,handles);
    elseif stype==3
        [cerchi oct]=generate_thickness(2,handles);
    else %stype==7
        cerchi=[0;0;0];
        oct=zeros(8,3);
    end
handles.cerchi=cerchi;
handles.oct=oct;
end
end
set(handles.axes1,'CameraPosition',cpos);
set(handles.axes1,'DataAspectRatio',[1 1 1]);
set(get(handles.axes1,'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(handles.axes1,'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(handles.axes1,'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
if stype ~= 7 && thick >0
set(handles.show_internal,'BackgroundColor',[0 1 0]);
set(handles.show_internal,'Enable','on');
set(handles.show_scloud,'BackgroundColor',[0 1 0]);
set(handles.show_scloud,'Enable','on');
set(handles.show_surface,'BackgroundColor',[0 1 0]);
set(handles.show_surface,'Enable','on');
set(handles.export_line,'BackgroundColor',[0 1 0]);
set(handles.export_line,'Enable','on');
set(handles.export_internal,'BackgroundColor',[1 0 0]);
set(handles.export_internal,'Enable','off');
set(handles.export_scloud,'BackgroundColor',[1 0 0]);
set(handles.export_scloud,'Enable','off');
set(handles.export_surface,'BackgroundColor',[1 0 0]);
set(handles.export_surface,'Enable','off');
else
    set(handles.show_internal,'BackgroundColor','r');
set(handles.show_internal,'Enable','off');
set(handles.show_scloud,'BackgroundColor','r');
set(handles.show_scloud,'Enable','off');
set(handles.show_surface,'BackgroundColor','r');
set(handles.show_surface,'Enable','off');
set(handles.export_line,'BackgroundColor',[0 1 0]);
set(handles.export_line,'Enable','on');
set(handles.export_internal,'BackgroundColor','r');
set(handles.export_internal,'Enable','off');
set(handles.export_scloud,'BackgroundColor','r');
set(handles.export_scloud,'Enable','off');
set(handles.export_surface,'BackgroundColor','r');
set(handles.export_surface,'Enable','off');
end
guidata(hObject, handles);

function alpha_Callback(hObject, eventdata, handles)
% hObject    handle to alpha (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 alpha as text
%        str2double(get(hObject,'String')) returns contents of alpha as a double

% --- Executes during object creation, after setting all properties.
function alpha_CreateFcn(hObject, eventdata, handles)
% hObject    handle to alpha (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function beta_Callback(hObject, eventdata, handles)
% hObject    handle to beta (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 beta as text
%        str2double(get(hObject,'String')) returns contents of beta as a double

% --- Executes during object creation, after setting all properties.
function beta_CreateFcn(hObject, eventdata, handles)
% hObject    handle to beta (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in zcomp.
function zcomp_Callback(hObject, eventdata, handles)
% hObject    handle to zcomp (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
val=(get(hObject,'Value'));
switch val
    case 1
        set(handles.text20,'String','z = 0');
        set(handles.c,'Enable','off');
        set(handles.d,'Enable','off');
        set(handles.e,'Enable','off');
        set(handles.f,'Enable','off');
    case 2
        set(handles.text20,'String','z = c*r^d + e*theta^f');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
    case 3
        set(handles.text20,'String','z = c*sin(r*d) + e*sin(theta*f)');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
    case 4
        set(handles.text20,'String','z = c*exp(d*r) + e*exp(f*theta)');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
    otherwise
        set(handles.text20,'String','z = c*log(r)^d + e*log(theta)^f');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
end
guidata(hObject, handles);
% Hints: contents = get(hObject,'String') returns zcomp contents as cell array
%        contents{get(hObject,'Value')} returns selected item from zcomp

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

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

function e_Callback(hObject, eventdata, handles)
% hObject    handle to e (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 e as text
%        str2double(get(hObject,'String')) returns contents of e as a double

% --- Executes during object creation, after setting all properties.
function e_CreateFcn(hObject, eventdata, handles)
% hObject    handle to e (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function f_Callback(hObject, eventdata, handles)
% hObject    handle to f (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 f as text
%        str2double(get(hObject,'String')) returns contents of f as a double

% --- Executes during object creation, after setting all properties.
function f_CreateFcn(hObject, eventdata, handles)
% hObject    handle to f (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function c_Callback(hObject, eventdata, handles)
% hObject    handle to c (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 c as text
%        str2double(get(hObject,'String')) returns contents of c as a double

% --- Executes during object creation, after setting all properties.
function c_CreateFcn(hObject, eventdata, handles)
% hObject    handle to c (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function d_Callback(hObject, eventdata, handles)
% hObject    handle to d (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 d as text
%        str2double(get(hObject,'String')) returns contents of d as a double

% --- Executes during object creation, after setting all properties.
function d_CreateFcn(hObject, eventdata, handles)
% hObject    handle to d (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function g_Callback(hObject, eventdata, handles)
% hObject    handle to g (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 g as text
%        str2double(get(hObject,'String')) returns contents of g as a double

% --- Executes during object creation, after setting all properties.
function g_CreateFcn(hObject, eventdata, handles)
% hObject    handle to g (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function h_Callback(hObject, eventdata, handles)
% hObject    handle to h (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 h as text
%        str2double(get(hObject,'String')) returns contents of h as a double

% --- Executes during object creation, after setting all properties.
function h_CreateFcn(hObject, eventdata, handles)
% hObject    handle to h (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function i_Callback(hObject, eventdata, handles)
% hObject    handle to i (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 i as text
%        str2double(get(hObject,'String')) returns contents of i as a double

% --- Executes during object creation, after setting all properties.
function i_CreateFcn(hObject, eventdata, handles)
% hObject    handle to i (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function [xo yo]=curv2cart(a,b,c,d,e,l,p,handles)
set(handles.timebar_text,'Visible','on','String','Generating Spiral');
drawnow update
s=0:p:l;
s2=-s;
x1=zeros(1,length(s));
y1=zeros(1,length(s));
x2=zeros(1,length(s));
y2=zeros(1,length(s));
k=a*s.^4+b*s.^3+c*s.^2+d*s+e;
k2=a*s2.^4+b*s2.^3+c*s2.^2+d*s2+e;
x1(2)=s(2);
y1(2)=0;
x2(2)=s2(2);
y2(2)=0;
perc=(length(s)*2-4)/100;
ls=length(s)-2;
for i=3:(length(s))
    sss=sprintf('Genetaring Spiral...%3.1f %%', i/perc);
    set(handles.timebar_text,'String',sss);
    drawnow update
    dth=k(i)*s(2);
    cth=(x1(i-1)-x1(i-2))/norm([x1(i-1) y1(i-1)]-[x1(i-2) y1(i-2)]);
    sth=(y1(i-1)-y1(i-2))/norm([x1(i-1) y1(i-1)]-[x1(i-2) y1(i-2)]);
    if sth>=0
        scorr=1;
    else scorr=-1;
    end
    newth=dth+scorr*acos(cth);
    xx=cos(newth);
    yy=sin(newth);
    x1(i)=(xx*s(2))+x1(i-1);
    y1(i)=(yy*s(2))+y1(i-1);
end

for i=3:(length(s))
    sss=sprintf('Genetaring Spiral...%3.1f %%', (i+ls)/perc);
    set(handles.timebar_text,'String',sss);
    drawnow update
    dth=k2(i)*s2(2);
    cth=(x2(i-1)-x2(i-2))/norm([x2(i-1) y2(i-1)]-[x2(i-2) y2(i-2)]);
    sth=(y2(i-1)-y2(i-2))/norm([x2(i-1) y2(i-1)]-[x2(i-2) y2(i-2)]);
    if sth>=0
        scorr=1;
    else scorr=-1;
    end
    newth=dth+scorr*acos(cth);
    xx=cos(newth);
    yy=sin(newth);
    x2(i)=(xx*s(2))+x2(i-1);
    y2(i)=(yy*s(2))+y2(i-1);
end
set(handles.timebar_text,'Visible','off');
xo=[fliplr(x2) x1];
yo=[fliplr(y2) y1];

function precision_Callback(hObject, eventdata, handles)
% hObject    handle to precision (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
x=str2double(get(hObject,'String'));
l=str2double(get(handles.lengt,'String'));
if x<=0
    set(hObject,'String','0.1');
    x=0.1;
elseif x>1
    set(hObject,'String','1');
    x=1;
end
    if l<=2*x
        set(hObject,'String',sprintf('%g', l/2));
    end

guidata(hObject, handles);

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

% --- Executes during object creation, after setting all properties.
function precision_CreateFcn(hObject, eventdata, handles)
% hObject    handle to precision (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in clear.
function clear_Callback(hObject, eventdata, handles)
% hObject    handle to clear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
        set(handles.text20,'String','z = 0');
        set(handles.c,'Enable','off');
        set(handles.d,'Enable','off');
        set(handles.e,'Enable','off');
        set(handles.f,'Enable','off');
        set(handles.text15,'String','r = a + b * theta');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.spiral_type,'Value',1);
        set(handles.zcomp,'Value',1);
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
handles.plane=[0 0 1];
set(handles.Xeq,'String','0');
set(handles.Yeq,'String','0');
set(handles.Zeq,'String','1');
vr=[[1 0;-1 0;0 1;0 -1]*null([0 0 1])';0 0 0];
fc=[1 5 3;2 5 3;2 5 4;1 4 5];
fv.vertices=vr;
fv.faces=fc;
handles.fv=fv;
handles.cerchi=[0;0;0];
handles.oct=zeros(8,3);
handles.surface=0;
handles.scloud=0;
handles.cloud=0;
handles.spiral=zeros(3,1);
set(handles.show_internal,'BackgroundColor','r');
set(handles.show_internal,'Enable','off');
set(handles.show_scloud,'BackgroundColor','r');
set(handles.show_scloud,'Enable','off');
set(handles.show_surface,'BackgroundColor','r');
set(handles.show_surface,'Enable','off');
set(handles.export_line,'BackgroundColor','r');
set(handles.export_line,'Enable','off');
set(handles.export_internal,'BackgroundColor','r');
set(handles.export_internal,'Enable','off');
set(handles.export_scloud,'BackgroundColor','r');
set(handles.export_scloud,'Enable','off');
set(handles.export_surface,'BackgroundColor','r');
set(handles.export_surface,'Enable','off');
guidata(hObject, handles);
refresh_plane(handles);
guidata(hObject, handles);

function [cerchi oct]=generate_thickness(a,handles)
surfface=str2double(get(handles.surfface,'String'));
stype=get(handles.spiral_type,'Value');
thick=str2double(get(handles.thick,'String'));
spir=handles.spiral;
set(handles.timebar_text,'Visible','on','String','Generating Thickness');
drawnow update;
if a==1
cerchi=[[0;0;0] spir(:,2:end)-spir(:,1:end-1)];
start=2;
else cerchi=spir(:,2:(end+1)/2)-spir(:,1:(end+1)/2-1);
    start=1;
end
oct=zeros(surfface,3,length(cerchi));
perc=(length(cerchi)-1)/100;
    for it=start:length(cerchi)
        sss=sprintf('Genetaring Thickness...%3.1f %%', it/perc);
        set(handles.timebar_text,'String',sss);
        drawnow update;
        cerc=cerchi(:,it);
        mm=norm(cerc)*thick;
        nullity=(null(cerc'))';
        if dot(cerc,[1 0 0])>0
            nullity=[-1 0;0 1]*nullity;
        end
        vects=gen_polygon(handles,surfface,mm);
        piu=zeros(3,surfface);
        piu=bsxfun(@plus,piu,spir(:,it));
        oct(:,:,it)=vects*nullity+piu';
    end
if a==2
    oct(:,:,end)=oct(:,:,end)-vects*nullity/2;
    cerchi=[cerchi fliplr(-cerchi)];
    oct= cat(3, oct, flipdim(-oct,3));
end
if stype==6
    piu=zeros(3,surfface);
    piu=bsxfun(@plus,piu,spir(:,1));
    oct(:,:,1)=piu';
    piu=zeros(3,surfface);
    piu=bsxfun(@plus,piu,spir(:,end));
    oct(:,:,end)=piu';
end

for it=start:length(cerchi)
    plot3(oct(:,1,it),oct(:,2,it),oct(:,3,it));
end
set(handles.timebar_text,'Visible','off');

function surfface_Callback(hObject, eventdata, handles)
% hObject    handle to surfface (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 surfface as text
%        str2double(get(hObject,'String')) returns contents of surfface as a double
x=floor(str2double(get(hObject,'String')));
if x<4;
x=4;
end
sss=sprintf('%d', x);
set(hObject,'String',sss);
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function surfface_CreateFcn(hObject, eventdata, handles)
% hObject    handle to surfface (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 && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function vects=gen_polygon(handles,surfface,mm)
div=0:2*pi/surfface:2*pi-2*pi/surfface;
vects=[cos(div')*mm sin(div')*mm];

function scloud=gen_scloud(handles,oct)
set(handles.timebar_text,'Visible','on','String','Generating Thickness');
drawnow update;
faces=length(oct(:,1,1))-1;
perc=(length(oct(1,1,:))-1)*faces/100;
oct=cat(1, oct, oct(1,:,:));
pl=1;
scloud=zeros(2*perc*100,3);
for slength=1:length(oct(1,1,:))-1
for polygon=1:faces
    it=(slength-1)*faces+polygon;
    sss=sprintf('Genetaring Surface Cloud...%3.1f %%', it/perc);
        set(handles.timebar_text,'String',sss);
        drawnow update;
p1=oct(polygon,:,slength);
p2=oct(polygon+1,:,slength);
p3=oct(polygon+1,:,slength+1);
p4=oct(polygon,:,slength+1);
p=[p1;p2;p3;p4];
[or,in]=min([norm(p1);norm(p2);norm(p3);norm(p4)]);
p=circshift(p,-in+1);
dx=p(2,:)-p(1,:);
dy=p(4,:)-p(1,:);
x1=p(1,:)/2+dx*rand;
y1=p(1,:)/2+dy*rand;
pp1=x1+y1;
x2=p(1,:)/2+dx*rand;
y2=p(1,:)/2+dy*rand;
pp2=x2+y2;
scloud(pl,:)=pp1;
pl=pl+1;
scloud(pl,:)=pp2;
pl=pl+1;
end
end

function cloud=gen_cloud(handles,oct)
set(handles.timebar_text,'Visible','on','String','Generating Internal Cloud');
drawnow update;
faces=length(oct(:,1,1));
perc=(length(oct(1,1,:)))*faces/100;
oct=cat(1, oct, oct(1,:,:));
pl=1;
j=2;    % j*faces is the number of points in every spital slice
pp=zeros(j*perc*100,3);

for slength=1:length(oct(1,1,:))-1
for polygon=1:faces-1
    it=(slength-1)*faces+polygon;
    sss=sprintf('Genetaring Internal Cloud...%3.1f %%', it/perc);
        set(handles.timebar_text,'String',sss);
        drawnow update;
    apenanti=mod(floor(faces/2)+polygon+1,faces);
    if apenanti==0,apenanti=faces;end
p1=oct(polygon+1,:,slength);
p2=oct(polygon,:,slength);
p3=oct(apenanti,:,slength);
p4=oct(apenanti,:,slength+1);
p5=oct(polygon+1,:,slength+1);
p6=oct(polygon,:,slength+1);
p=[p1;p2;p3;p4;p5;p6];

dy=p2-p1;
dz=p3-p1;
dx=p5-p1;

for k=1:j
dyp=dy*rand;
dxp=dx*rand;
dzn=norm(dy-dyp)*norm(dz)/norm(dy);
dzp=dz./norm(dz)*rand*dzn;
pp(pl,:)=p(1,:)+dzp+dxp+dyp;
pl=pl+1;
end
end
end
cloud=pp;


% Demo: on-line design optimization for DCM of fMRI data.
% This demo simplifies the network identification of Friston et al. (2003).
% In brief, photic input enters V1, which is reciprocally connected to V5.
% The goal of the experiment is to assess whether attention modulates the
% feedforward connection from V1 to V5. This is addressed using Bayesian
% model comparison given fMRI data (i.e. model 1: attention modulates the
% V1->V5 connection; model 2: no modulatory effect). Within the session,
% each block consists of 16 seconds of stimulation and 16 of rest. The
% on-line design optimization consists in deciding, before each block,
% whether we modulate subjects' attention. This is done by comparing the
% design efficiency  of two canonical block designs (i.e. with and without
% attentional modulation).
% NB: the procedure is adaptative, because it updates the posterior on
% unknown model parameters after each block. This is why the design
% efficiency inceases across time.

close all
clear variables

% Basic settings
n_t = 16; % number of time samples per block
nblocks = 10; % number of blocks
nreg = 2; % number of regions
TR = 3e0; % sampling period (in sec)
microDT = 5e-2; % micro-time resolution (in sec)
f_fname = @f_DCMwHRF;
g_fname = @g_HRF3;

% construct atomic designs
nu = 2;
u1 = [0,ones(1,floor(n_t/2))];
u1(end:n_t) = 0;
u2 = zeros(1,n_t);
u = {[u1;u2];[u1;u1]}; % u{1}/u{2}: w/wo attentinal modulation

nm = 2; % # candidate models (see below)
truemodel = 1; % index of true model (which generates the data)

% model 1: u_att modulates connection from V1 to V5
A = [0 1
    1 0];
B{1} = zeros(nreg,nreg);
B{2} = zeros(nreg,nreg);
B{2}(2,1) = 1;
C = [1 0
     0 0];
D{1} = [0 0
    0 0];
D{2} = zeros(nreg,nreg);
D{3} = zeros(nreg,nreg);
[o4design{1},dim{1}] = getOptions4dcm(A,B,C,D,TR,microDT,n_t,1,1,1);

% model 1: no modulatory effect of attention
A = [0 1
    1 0];
nreg = size(A,1);
B{1} = zeros(nreg,nreg);
B{2} = zeros(nreg,nreg);
C = [1 0
     0 0];
D{1} = [0 0
    0 0];
D{2} = zeros(nreg,nreg);
D{3} = zeros(nreg,nreg);
[o4design{2},dim{2}] = getOptions4dcm(A,B,C,D,TR,microDT,n_t,1,1,1);

o4design{truemodel}.verbose = 0;

% simu parameters
t_A = exp([ -0.5
            -0.5
            ]);
t_Aself = -0;
t_B{1} = [];
t_B{2} = exp([ -0.5 ]);
t_C = exp([ -0.5 ]);
t_D{1} = [];
t_D{2} = [];
theta = zeros(dim{truemodel}.n_theta,1);
phi = zeros(dim{truemodel}.n_phi,1);
theta(o4design{truemodel}.inF.indA) = t_A;
for i=1:nu
    theta(o4design{truemodel}.inF.indB{i}) = t_B{i};
end
theta(o4design{truemodel}.inF.indC) = t_C;
alpha = Inf; % state noise precision
sigma = 5e-1; % measurement noise precision
x0 = zeros(dim{truemodel}.n,1); % initial conditions

% prepare graphics & montoring variables
hf = figure('color',[1 1 1]);
ha = subplot(3,2,1,'parent',hf,'nextplot','add','xlim',[1 nblocks+1]);
xlabel(ha,'time (blocks)')
ylabel(ha,'design efficiency')
ha2 = subplot(3,2,3,'parent',hf,'nextplot','add','xlim',[1 n_t*nblocks]);
xlabel(ha2,'time (scans)')
ylabel(ha2,'BOLD signal')
ha3 = subplot(3,2,2,'parent',hf,'nextplot','add','xlim',[1 nblocks+1]);
xlabel(ha3,'time (blocks)')
ylabel(ha3,'log p(y|m_1) -log p(y|m_2)')
e = zeros(2,1);
Y = zeros(dim{truemodel}.p,n_t*nblocks);
U = zeros(2,n_t*nblocks);
F = zeros(2,nblocks);
eb = zeros(1,nblocks);
vb = zeros(1,nblocks);

% on-line experiment

for tt=1:nblocks

    % 1- find best design given current information
    fprintf(1,'\n')
    fprintf(1,['-- Optimizing design (block ',num2str(tt),')...'])
    fprintf(1,'\n')
    for i=1:length(u) %loops over experimental designs
        fprintf(1,['- Candidate design #',num2str(i),'...'])
        fprintf(1,'\n')
        [e(i,tt)] = VBA_designEfficiency(f_fname,g_fname,dim,o4design,u{i},'models');
    end
    [em,ind] = max(e(:,tt));
    U(:,(tt-1)*n_t+1:tt*n_t) = u{ind};
    fprintf(1,['Optimizing design (block ',num2str(tt),')...  OK.'])
    fprintf(1,'\n')
    plot(ha,tt,e(1,tt)','ro')
    plot(ha,tt,e(2,tt)','go')
    legend(ha,{'u_{att} = off','u_{att} = on'},'Location','southeast','Orientation','horizontal')

    % 2- simulate BOLD response to chosen design under true model
    fprintf(1,['-- Simulating data (block ',num2str(tt),')...  '])
    [y,x,x0,eta,ee] = VBA_simulate (n_t,f_fname,g_fname,theta,phi,u{ind},alpha,sigma,o4design{truemodel},x0);
    Y(:,(tt-1)*n_t+1:tt*n_t) = y;
    x0 = x(:,end);

    try
        set(pl(1), 'XData', 1 : tt*n_t);
        set(pl(1), 'YData', [get(pl(1), 'YData') y(1,:)]);
        set(pl(2), 'XData', 1 : tt*n_t);
        set(pl(2), 'YData', [get(pl(2), 'YData') y(2,:)]);
    catch
        pl(1) = plot(ha2,1:n_t,y(1,:),'m');
        pl(2) = plot(ha2,1:n_t,y(2,:),'b');
    end
    legend(ha2,{'V1','V5'},'Location','southeast','Orientation','horizontal')
    fprintf(1,[' OK.'])
    fprintf(1,'\n')
    drawnow

    % 3- invert both models given new piece of dataset
    % NB: priors for the next block are updated to current posterior
    fprintf(1,['-- VB (block ',num2str(tt),'):   inverting model       '])
    for j=1:length(o4design)
        fprintf(1,repmat('\b',1,6))
        fprintf(1,[num2str(j),'/',num2str(length(o4design)),'...'])
        o4design{j}.DisplayWin = 0;
        o4design{j}.verbose = 0;
        [posterior,out] = VBA_NLStateSpaceModel(y,u{ind},f_fname,g_fname,dim{j},o4design{j});
        o4design{j}.priors = posterior;
        o4design{j}.priors.muX0 = posterior.muX(:,end);
        o4design{j}.priors.SigmaX0 = posterior.SigmaX.current{end};
        if tt > 1
            F(j,tt) = out.F + F(j,tt-1);
        else
            F(j,tt) = out.F;
        end
        OUT(j,tt).out = out;
        OUT(j,tt).posterior = posterior;
    end
    plot(ha3,tt,F(1,tt)-F(2,tt),'k*')

    eb(tt) = OUT(1,tt).posterior.muTheta(OUT(1,tt).out.options.inF.indB{2});
    vb(tt) = OUT(1,tt).posterior.SigmaTheta(OUT(1,tt).out.options.inF.indB{2},OUT(1,tt).out.options.inF.indB{2});

    fprintf(1,repmat('\b',1,24))
    fprintf(1,[' OK.'])
    fprintf(1,'\n')

end

ha4 = subplot(3,2,4,'parent',hf,'nextplot','add','xlim',[0 nblocks+1]);
xlabel(ha4,'time (blocks)')
ylabel(ha4,'modulatory effect')
plotUncertainTimeSeries(eb',1.96^2*vb',[],ha4)
hold(ha4,'on')
plot(ha4,[0,nblocks+1],[t_B{2},t_B{2}],'g--')

ha5 = subplot(3,2,5,'parent',hf);
imagesc(U,'parent',ha5)
title(ha5,'chosen (online) design')
xlabel(ha5,'time (scans)')
hold(ha5,'on')
plot(get(ha5,'xlim'),[1.5 1.5],'k')
set(ha5,'ytick',[1,2],'yticklabel',{'u1','u2'})
colormap(flipud(bone))

% invert full datasets at once
n_t = size(Y,2);
B{2}(2,1) = 1; % add modulatory effect (true model)
[OPT,DIM] = getOptions4dcm(A,B,C,D,TR,microDT,n_t,1,1,1);
[posterior,out] = VBA_NLStateSpaceModel(Y,U,f_fname,g_fname,DIM,OPT);


function [W,result] = IHR(Ws,npos,gama,afa,yuzhi)
global eta;
global TrainSetX;
global TestSetX;
global TestSetY;
global kneighbor_testp;

global W0;
global s11;
global w1;
global index1;
W0 = Ws;
w1 = Ws;

tempsum1 = 0;
for i=1:size(TestSetX,2)
    tempKN = kneighbor_testp(i,:);
    tempTuples = TestSetX(:,tempKN);
    s1 = w1'*tempTuples;
    p1 = 1./(1 + exp(-s1));
    tempsum1 = tempsum1 + (sum(p1)/size(kneighbor_testp,2)-1/(1+exp(-w1'*TestSetX(:,i))))^2;
end

tempsum2 = 0;
for i=1:size(TestSetX,2)
    tempsum2 = tempsum2 + (1/(1+exp(-w1'*TestSetX(:,i))) - 0.5)^2;
end

s1 = w1'*TestSetX;
p1 = 1./(1 + exp(-s1));

f = ((w1)'*(w1))+afa*tempsum1/size(TestSetX,2)-gama*tempsum2/size(TestSetX,2)+eta*(sum(p1)-npos)^2/size(TestSetX,2); %07-12-31
fprintf('initial value...%g\n',f);
index1 = 0;

result(1,1) = getResult(p1,TestSetY);
ff(1,1) = f;
warning off;
while index1 < 100

    temp11 = zeros(size(TestSetX,1),1);
    s11 = zeros(size(TestSetX,1),1);
    for i=1:size(TestSetX,2)
        tempKN = kneighbor_testp(i,:);
        tempTuples = TestSetX(:,tempKN);
        s1 = w1'*tempTuples;
        p1 = 1./(1 + exp(-s1));
        tmp_p1 = sum(p1)/size(kneighbor_testp,2)-1/(1+exp(-w1'*TestSetX(:,i)));
        p2 = exp(-s1)./((1 + exp(-s1)).^2);
        for k = 1:size(kneighbor_testp,2)
            temp11 = temp11 + tempTuples(:,k)*p2(1,k);
        end
        temp11 = temp11/size(kneighbor_testp,2) - (exp(-w1'*TestSetX(:,i))/(1+exp(-w1'*TestSetX(:,i)))^2)*TestSetX(:,i);
        s11 = s11 + 2*tmp_p1*temp11;
    end
    s11 = afa*s11/size(TestSetX,2); %

    s12 = zeros(size(TestSetX,1),1);
    for i = 1:size(TestSetX,2)
        s12 = s12 + 2*gama*(1/(1+exp(-w1'*TestSetX(:,i))) - 0.5)*((exp(-w1'*TestSetX(:,i)))/(1+exp(-w1'*TestSetX(:,i)))^2)*TestSetX(:,i);
    end
    s12 = s12/size(TestSetX,2);

    s1 = w1'*TestSetX;
    p1 = 1./(1 + exp(-s1));
    tmps13 = 2*eta*(sum(p1)-npos)*(exp(-w1'*TestSetX)./(1+exp(-w1'*TestSetX)).^2);
    s13 = sum(scale_cols(TestSetX,tmps13),2);
    s13 = s13/size(TestSetX,2);

    if [s11-s12+s13+2*(w1)]'*[s11-s12+s13+2*(w1)] < yuzhi^2
        break;
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if index1 == 0
        d0 = -s11+s12-s13-2*(w1);
    end
    if index1 > 0
        afa0 = ([s11-s12+s13+2*(w1)]'*[s11-s12+s13+2*(w1)-temp_s11-temp_s12])/([temp_s11+temp_s12]'*[temp_s11+temp_s12]);
        d1 = [-s11+s12-s13-2*(w1)] + afa0*d0;
        d0 = d1;
    end

    temp_s11 = s11;
    temp_s12 = -s12+s13+2*(w1);

    s11 = d0;

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    beta = 0;

    options = optimset('LargeScale','on');
    [x,fval] = fminunc(@objfun,beta,options);

    beta = x;
    if beta == 0
        break;
    end
    w1 = w1 + beta*d0;

    tempsum1 = 0;
    for i=1:size(TestSetX,2)
        tempKN = kneighbor_testp(i,:);
        tempTuples = TestSetX(:,tempKN);
        s1 = w1'*tempTuples;
        p1 = 1./(1 + exp(-s1));
        tempsum1 = tempsum1 + (sum(p1)/size(kneighbor_testp,2)-1/(1+exp(-w1'*TestSetX(:,i))))^2;
    end

    tempsum2 = 0;
    for i=1:size(TestSetX,2)
        tempsum2 = tempsum2 + (1/(1+exp(-w1'*TestSetX(:,i))) - 0.5)^2;
    end

    s1 = w1'*TestSetX;
    p1 = 1./(1 + exp(-s1));

    f = ((w1)'*(w1))+afa*tempsum1/size(TestSetX,2)-gama*tempsum2/size(TestSetX,2)+eta*(sum(p1)-npos)^2/size(TestSetX,2); %07-12-31

    s1 = w1'*TestSetX;
    p1 = 1./(1 + exp(-s1));
    index1 = index1+1;
    result(1,index1+1) = getResult(p1,TestSetY);
    ff(1,index1+1) = f;

    fprintf('iterating...%g value : %g...the accuracy:%g\n',index1,f,getResult(p1,TestSetY));

end
W = w1;


function [G1,C,impact,eu,F]=schur_solver(g0,g1,c,psi,pi,continuous,check_exist,check_uniq,n_v)
% Solver based on Schur decomposition (This is based on Sims's gensys, but adjusted
%    to take advantage of special case that applies to heterogeneous agent models).
%
% by SeHyoun Ahn, Dec 2016
%
% REFERENCES:
%    * Sims, Christopher A. "Solving linear rational expectations models."
%         Computational economics 20.1 (2002): 1-20.
%    * Ahn, SeHyoun, Greg Kaplan, Benjamin Moll, Thomas Winberry, and
%         Christian Wolf. "When Inequality Matters for Macro and Macro Matters
%         for Inequality."
%
% PARAMETERS:
%    Check Sims's paper for notation or Our Paper for notation
%
%    XXXXX DO NOT USE DISCRETE TIME VERSION. IT PROBABLY IS WRONG XXXXXX
%    The issue is noted in < https://github.com/gregkaplan/phact/issues/1 >
%
%    continuous = 1 for a continuous time problem (default)
%                0 for a discrete time problem
%
%    check_exist = 1 check for existence of solution (default)
%                 0 existence has been checked before
%    check_uniq = 0 do not check for uniqueness (default)
%                1 check for uniqueness
%    n_v = number of unstable roots
%
% OUPUTS:
%    eu(1) = 1 solution exists
%            0 no stable solution
%           -5 Flag for checking existence is off
%    eu(2) = 1 solution is unique
%            0 solution is not unique
%           -5 Flag for checking uniqueness is off
%
% SYNTAX:
% [G1,C,impact,eu,F]=schur_solver(g0,g1,c,psi,pi,continuous,check_exist,check_uniq,varargin)

%% Set Default Values %%
switch nargin
    case 8
        n_v = -1;
    case 7
        check_uniq = 0;
        n_v = -1;
    case 6
        check_uniq = 0;
        check_exist = 1;
        n_v = -1;
    case 5
        check_uniq = 0;
        check_exist = 1;
        continuous = 1;
        n_v = -1;
    case 1:4
        error('Insufficient Number of Input Variables');
end

realsmall = sqrt(eps)*10;
eu = [-5;-5];
n = size(g1,1);

%% Schur Decomposition
[U,T] = schur(full(g1),'real');
if continuous
    g_eigs = real(ordeig(T));
    nunstab = sum(g_eigs>0);
    if n_v > -1
        [aux,ind] = sort(g_eigs,'descend');
        locs = ones(n,1);
        locs(ind(1:n_v)) = 0;
        [U,T] = ordschur(U,T,locs);
        if nunstab > n_v
            warning('<schur_solver>: There are more than n_v number of positive eigenvalues with smallest values:');
            disp(aux(n_v+1:nunstab));
        elseif nunstab < n_v
            warning('<schur_solver>: There are less than n_v number of positive eigenvalues:');
            disp(aux(nunstab+1:n_v));
        end
        nunstab = n_v;
    else
        [U,T] = ordschur(U,T,'lhp');
    end
else
    g_eigs = abs(ordeig(T));
    nunstab = sum(g_eigs>1);
    if n_v > -1
        [aux,ind] = sort(g_eigs,'descend');
        locs = ones(n,1);
        locs(ind(1:n_v)) = 0;
        [U,T] = ordschur(U,T,locs);
        if nunstab > n_v
            warning('<schur_solver>: There are more than n_v number of positive eigenvalues with smallest values:');
            disp(aux(n_v+1:nunstab));
        elseif nunstab < n_v
            warning('<schur_solver>: There are less than n_v number of positive eigenvalues:');
            disp(aux(nunstab+1:n_v));
        end
        nunstab = n_v;
    else
	[U,T] = ordschru(U,T,'udi');
    end
end

u1 = U(:,1:n-nunstab)';
u2 = U(:,n-nunstab+1:n)';

etawt = u2*pi;
[ueta,deta,veta] = svd(etawt);
md = min(size(deta));
bigev = find(diag(deta(1:md,1:md))>realsmall);
ueta = ueta(:,bigev);
veta = veta(:,bigev);
deta = deta(bigev,bigev);

if check_exist
    zwt = u2*psi;
    [uz,dz,vz] = svd(zwt);
    md = min(size(dz));
    bigev = find(diag(dz(1:md,1:md))>realsmall);
    uz = uz(:,bigev);
    vz = vz(:,bigev);
    dz = dz(bigev,bigev);

    if isempty(bigev)
        eu(1) = 1;
    else
        eu(1) = (norm(uz-ueta*ueta'*uz,'fro') < realsmall*n);
    end

    if (~eu(1) && (n_v == -1))
        warning('<schur_solver>: Solution does not exist');
    end
    impact = real(-pi*veta*(deta\ueta')*uz*dz*vz'+psi);
else
    impact = real(-pi*veta*(deta\ueta')*u2*psi+psi);
end

G1 = U*T*spdiags([ones(n-nunstab,1);zeros(nunstab,1)],0,n,n)*U';
G1 = real(G1);

if check_uniq
    [~,deta1,veta1] = svd(u1*pi);
    md = min(size(deta1));
    bigev = find(diag(deta1(1:md,1:md))>realsmall);
    veta1 = veta1(:,bigev);
    if isempty(veta1)
        eu(2) = 1;
    else
        eu(2) = norm(veta1-veta*veta'*veta1,'fro')<realsmall*n;
    end
end
F = u1(:,1:nunstab)'*inv(u1(:,nunstab+1:end)');
impact = [F*psi(nunstab+1:end,:);psi(nunstab+1:end,:)];
C = c;  	% constant term is not coded yet


function [fc,core]=qtt_tucker_m(tt, sz, tol)
%Compute the QTT-Tucker representation of TT
%   [FC,CORE]=QTT_TUCKER_M(TT, SZ, TOL) Computes the QTT-Tucker
%   representation of TT-tensor. This is a technical function: use
%   corresponding constructors of the QTT-Tucker class
%
%
% TT-Toolbox 2.2, 2009-2012
%
%This is TT Toolbox, written by Ivan Oseledets et al.
%Institute of Numerical Mathematics, Moscow, Russia
%webpage: http://spring.inm.ras.ru/osel
%
%For all questions, bugs and suggestions please mail
%ivan.oseledets@gmail.com
%---------------------------

d = tt.d;
n = tt.n;
rcr = tt.r;

fc = cell(d,1);

% Initial orthogonalization - 1->d
for i=1:d-1
    cr = tt{i};
    cr = reshape(cr, rcr(i)*n(i), rcr(i+1));
    [cr, rv]=qr(cr, 0);
    cr2 = tt{i+1};
    cr2 = rv*reshape(cr2, rcr(i+1), n(i+1)*rcr(i+2));
    rcr(i+1) = size(cr,2);
    tt{i} = reshape(cr, rcr(i), n(i), rcr(i+1));
    tt{i+1} = reshape(cr2, rcr(i+1), n(i+1), rcr(i+2));
end;

% Split tucker factors from d->1
core = tt;
nextcr = core{d};
rtuck = zeros(d,1);
for i=d:-1:1
    cr = nextcr;
    cr = permute(cr, [2, 1, 3]);
    cr = reshape(cr, n(i), rcr(i)*rcr(i+1));
    [u,s,v]=svd(cr, 'econ');
    s = diag(s);
    nrm = norm(s);
    r = my_chop2(s, tol*nrm); % !!!!!!
    rtuck(i) = r;
    if (i>1)
        fc{i} = u(:,1:r);
        cr = diag(s(1:r))*v(:,1:r)';
        cr = reshape(cr, r, rcr(i), rcr(i+1));
        cr = permute(cr, [1, 3, 2]);
        cr = reshape(cr, r*rcr(i+1), rcr(i));
        [cr,rv] = qr(cr, 0);
        cr2 = core{i-1};
        cr2 = reshape(cr2, rcr(i-1)*n(i-1), rcr(i));
        cr2 = cr2*(rv.');
        rcr(i) = size(cr, 2);
        nextcr = reshape(cr2, rcr(i-1), n(i-1), rcr(i));
        cr = reshape(cr, r, rcr(i+1), rcr(i));
        core{i} = permute(cr, [3, 1, 2]);
    else
        cr = v(:,1:r)';
        cr = reshape(cr, r, rcr(i), rcr(i+1));
        core{i} = permute(cr, [2, 1, 3]);
        fc{i} = u(:,1:r)*diag(s(1:r));
    end;
end;

% Quantics approximation
for i=1:d
    %d0 = log2(n(i));
    fc{i} = tt_tensor(fc{i});
    szc=sz{i}; d0=numel(szc); m0=szc(end); szc=szc(:);
    %fc{i} = tt_reshape(fc{i}, [2*ones(1,d0-1), 2*rtuck(i)], tol);
    fc{i}=tt_reshape(fc{i},[szc(1:end-1); m0*rtuck(i)],tol);
    nocore = fc{i}{d0}; % rqtt, 2*rtuck, 1
    rqtt = size(nocore, 1);
    if (i<d)
        % Play with QRs: fc{i}->cr{i}->cr{i+1}->fc{i+1}
        nocore = reshape(nocore, rqtt*m0, rtuck(i));
        [ocore, nocore]=qr(nocore, 0);
        cr1 = core{i};
        cr1 = permute(cr1, [2, 1, 3]);
        cr1 = reshape(cr1, rtuck(i), rcr(i)*rcr(i+1));
        cr1 = nocore*cr1;
        rtuck(i) = size(cr1, 1);
        fc{i}{d0} = reshape(ocore, rqtt, m0, rtuck(i));

        cr1 = reshape(cr1, rtuck(i)*rcr(i), rcr(i+1));
        [cr1, rv]=qr(cr1, 0);
        cr2 = core{i+1};
        cr2 = reshape(cr2, rcr(i+1), rtuck(i+1)*rcr(i+2));
        cr2 = rv*cr2;
        rcr(i+1) = size(cr1, 2);
        cr1 = reshape(cr1, rtuck(i), rcr(i), rcr(i+1));
        core{i} = permute(cr1, [2,1,3]);
        cr2 = reshape(cr2, rcr(i+1), rtuck(i+1), rcr(i+2));
        cr2 = permute(cr2, [1, 3, 2]);
        cr2 = reshape(cr2, rcr(i+1)*rcr(i+2), rtuck(i+1));
        [cr2, rv]=qr(cr2, 0);
        fc{i+1} = fc{i+1}*(rv.');
        rtuck(i+1) = size(cr2, 2);
        cr2 = reshape(cr2, rcr(i+1), rcr(i+2), rtuck(i+1));
        core{i+1} = permute(cr2, [1, 3, 2]);
    else
        fc{i}{d0} = reshape(nocore, rqtt, m0, rtuck(i));
    end;
end;

end


function BoschettiEnc(img, name, bos_rateE, bos_rateRGB, nBit, tmo_operator)
%
%
%       BoschettiEnc(img, name, bos_rateE, bos_rateRGB, nBit)
%
%
%       Input:
%           -img: input HDR image
%           -name: is output name of the image. If img is empty
%                  an HDR image with filename 'name' is loaded
%           -bos_rateE: JPEG2000 compression rate for the E layer
%           -bos_rateRGB: JPEG2000 compression rate for the RGB layer
%           -nBit: number of bit of the encoding. The maximum is 16.
%           -tmo_operator: an handle to a tone mapping operator
%
%
%     Copyright (C) 2012  Francesco Banterle
%
%     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/>.
%

if(~exist('name', 'var'))
    name = 'bosc_enc';
end

if(~exist('bos_rateRGB', 'var'))
    rateRGB = 15;
else
    rateRGB = bos_rateRGB;
end

if(~exist('bos_rateE', 'var'))
    rateE = 15;
else
    rateE = bos_rateE;
end

if(~exist('nBit','var'))
    nBit = 16;
end

if(~exist('tmo_operator','var'))
    tmo_operator = @ReinhardTMO;
end

%Tone mapping
imgTMO = tmo_operator(img);
%LDR Encoding
imgTMO = GammaTMO(imgTMO, 2.2, 0.0, 0);

%Quantization
maxVal = 2^nBit - 1;
imgTMO = round(imgTMO * maxVal) / maxVal;

%Computing E
epsilon = 1e-4;
epi = 1.0 / maxVal;
E = log2(img ./ (imgTMO + epi) + epsilon);
E = mean(E, 3);

%Encoding E
maxE = max(E(:));
minE = min(E(:));
Eq = (E - minE) / (maxE - minE);

%metadata string
metatadata = [num2str(nBit), ' ', num2str(maxE), ' ', num2str(minE)];

if(nBit == 16)
    Eq = uint16(Eq * maxVal);
end

imwrite(Eq,[name,'_bos_E.jp2'], 'Mode', 'lossy', 'CompressionRatio', rateE);

%Decoding E
EqDec = double(imread([name, '_bos_E.jp2'])) / maxVal;
EDec = EqDec * (maxE - minE) + minE;

%Computing RGB
RGB = zeros(size(img));
div = 2.^EDec;
for i=1:size(img, 3)
    RGB(:,:,i) = (img(:,:,i) ./ div);
end

%Encoding RGB
if(nBit == 16)
    RGB = uint16(RGB * maxVal);
end

nameOut = [name,'_bos_RGB.jp2'];
imwrite(RGB, nameOut, 'Mode', 'lossy', 'CompressionRatio', rateRGB, 'Comment', metatadata);
end


%MDL_FANUC10L  Create kinematic model of Fanuc AM120iB/10L robot
%
% MDL_FANUC10L is a script that creates the workspace variable R which
% describes the kinematic characteristics of a Fanuc AM120iB/10L robot
% using standard DH conventions.
%
% Also defines the workspace vector:
%   q0   mastering position.
%
% Notes::
% - SI units of metres are used.
%
% Author::
%  Wynand Swart,
%  Mega Robots CC, P/O Box 8412, Pretoria, 0001, South Africa,
%  wynand.swart@gmail.com
%
% See also mdl_irb140, mdl_m16, mdl_motomanHP6, mdl_puma560, SerialLink.

% MODEL: Fanuc, AM120iB/10L, 6DOF, standard_DH

% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for Matlab (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.

%Cell: 073-1555-430
%30 Sep 2007
%Fanuc AM120iB/10L robot

%            theta    d      a    alpha
clear L
L(1) = Link([0        0     0.15  -pi/2   0  ]);
L(2) = Link([0        0     0.77   pi     0  ]);
L(3) = Link([0        0     0.1   -pi/2   0  ]);
L(4) = Link([0       -0.96  0      pi/2   0  ]);
L(5) = Link([0        0     0     -pi/2   0  ]);
L(6) = Link([0       -0.1   0      0      0  ]);
%##########################################################
%Pose 0; At MASTERING position;
%##########################################################
q0 =[0   -pi/2   0   0   0   0];
R=SerialLink(L, 'name', 'Fanuc AM120iB/10L');
%##########################################################


function innerpro = cinnerprodgeneral(x, y)
% Computes the Euclidean inner product between x and y in the complex case
%
% function innerpro = cinnerprodgeneral(x, y)
%
% The input x and y are numeric data structures which can be defined
% recursively by arrays, structs and cells. Each part of x and y should
% be a struct which contains the fields real and iamg which indicate
% the real and imaginary part of the stored complex numbers. The inner
% product between x and y is defined as sum(real(conj(x(:)).*y(:))).
% The return is the sum of the inner products over each part of x and y.
% In case that x and y are structs with different fields, the inner products
% are computed only for the common fields.
%
% Note: Operations between dlarrays containing complex numbers have been
% introduced in Matlab R2021b or later. This file is only useful for Matlab
% R2021a or earlier. It will be discarded when Matlab R2021b is stable.
%
% See also: innerprodgeneral, manoptADhelp

% This file is part of Manopt: www.manopt.org.
% Original author: Xiaowen Jiang, Aug. 31, 2021.
% Contributors: Nicolas Boumal
% Change log:

    if ~((isstruct(x) && isstruct(y)) || (iscell(x) && iscell(y))...,
            || (isnumeric(x) && isnumeric(y)) || (isstruct(x) && isnumeric(y)))

        up = MException('manopt:autodiff:cinnerprodgeneral' ,...
            'cinnerprodgeneral should only accept structs, cells or arrays.');
        throw(up);

    end
    % recursively compute the inner product
    if isstruct(x) && isstruct(y) && (~isfield(x,'real')) && (~isfield(y,'real'))
        innerpro  = cinnerprodgeneral_struct(x,y);
    elseif iscell(x) && iscell(y)
        innerpro = cinnerprodgeneral_cell(x,y);
    else
        xconj = cconj(x);
        product = cdottimes(xconj,y);
        innerpro = sum(creal(product),'all');
        % slower
        % xcol = cmat2col(x);
        % innerpro = creal(cprod(ctransp(xcol),xcol));
    end

    % struct case
    function innerpro = cinnerprodgeneral_struct(x,y)
        innerpro = 0;
        elemsx = fieldnames(x);
        elemsy = fieldnames(y);
        % find the common fields
        [elems,ix,iy] = intersect(elemsx,elemsy, 'stable');
        nelems = numel(elems);
        for ii = 1:nelems
            if isstruct(x.(elemsx{ix(ii)})) && (~isfield(x.(elemsx{ix(ii)}),'real'))...,
                    && (~isfield(y.(elemsy{iy(ii)}),'real'))
                innerpro = innerpro + cinnerprodgeneral_struct(...,
                    x.(elemsx{ix(ii)}),y.(elemsy{iy(ii)}));
            elseif iscell(x.(elemsx{ix(ii)}))
                innerpro = innerpro + cinnerprodgeneral_cell(...,
                    x.(elemsx{ix(ii)}),y.(elemsy{iy(ii)}));
            else
                xconj = cconj(x.(elemsx{ix(ii)}));
                product = cdottimes(xconj, y.(elemsy{iy(ii)}));
                innerpro = innerpro + sum(creal(product), 'all');
            end
        end
    end

    % cell case
    function innerpro = cinnerprodgeneral_cell(x,y)
        innerpro = 0;
        ncell = length(x);
        for ii = 1:ncell
            if isstruct(x{ii}) && (~isfield(x{ii},'real')) && (~isfield(y{ii},'real'))
                innerpro = innerpro + cinnerprodgeneral_struct(...,
                    x{ii},y{ii});
            elseif iscell(x{ii})
                innerpro = innerpro + cinnerprodgeneral_cell(...,
                    x{ii},y{ii});
            else
                xconj = cconj(x{ii});
                product = cdottimes(xconj, y{ii});
                innerpro = innerpro + sum(creal(product), 'all');
            end
        end
    end

end


function [A, Z, title, key, mtype] = RBfix (filename)
%RBFIX read a possibly corrupted matrix from a R/B file
% (assembled format only).  Usage:
%
% [A Z title key mtype] = RBfix (filename)
%
% The Rutherford/Boeing format stores a sparse matrix in a file in compressed-
% column form, using 3 arrays: Ap, Ai, and Ax.  The row indices of entries in
% A(:,j) are in Ai(p1:p2) and the corresponding numerical values are Ax(p1:p2),
% where p1 = Ap(j) and p2 = Ap(j+1)-1.  The row indices ought to be sorted, and
% no duplicates should appear, but this function ignores that requirement.
% Duplicate entries are summed if they exist, and A is returned with sorted
% columns.  Symmetric matrices are stored with just their lower triangular
% parts in the file.  Normally, it is an error if entries are present in the
% upper triangular part of a matrix that is declared in the file to be
% symmetric.  This function simply ignores those entries.
%
% If CHOLMOD is installed, this function is faster and uses less memory.
%
% Example:
%
%   load west0479
%   RBwrite ('mywest', west0479, [ ], 'My west0479 file', 'west0479') ;
%   [A Z title key mtype] = RBfix ('mywest') ;
%   isequal (A, west0479)
%   title, key, mtype
%
% See also mread, RBread, RBwrite, RBreade, sparse2.

% Optionally uses the CHOLMOD sparse2 mexFunction.

% Copyright 2007, Timothy A. Davis

%-------------------------------------------------------------------------------
% read in the raw contents of the Rutherford/Boeing file
%-------------------------------------------------------------------------------

[mtype Ap Ai Ax title key nrow] = RBraw (filename) ;
mtype = lower (mtype) ;

%-------------------------------------------------------------------------------
% determine dimension, number of entries, and convert numerical entries
%-------------------------------------------------------------------------------

% number of columns
ncol = length (Ap) - 1 ;

% number of entries
nz = length (Ai) ;

% check column pointers
if (any (Ap ~= sort (Ap)) | (Ap (1) ~= 1) | (Ap (ncol+1) - 1 ~= nz))	    %#ok
    error ('invalid column pointers') ;
end

% check row indices
if ((double (max (Ai)) > nrow) | double (min (Ai)) < 1)			    %#ok
    error ('invalid row indices') ;
end

% Ax can be empty, for a p*a matrix
if (~isempty (Ax))
    if (mtype (1) == 'c')
	% Ax is real, with real/imaginary parts interleaved
	if (2 * nz ~= length (Ax))
	    error ('invalid matrix') ;
	end
	Ax = Ax (1:2:end) + (1i * Ax (2:2:end)) ;
    elseif (mtype (1) == 'i')
	Ax = double (Ax) ;
    end
    % numerical values must be of the right size
    if (nz ~= length (Ax))
	error ('invalid matrix') ;
    end
end

%-------------------------------------------------------------------------------
% create the triplet form
%-------------------------------------------------------------------------------

% construct column indices
Aj = zeros (nz,1) ;
for j = 1:ncol
    p1 = Ap (j) ;
    p2 = Ap (j+1) - 1 ;
    Aj (p1:p2) = j ;
end

%-------------------------------------------------------------------------------
% create the sparse matrix form
%-------------------------------------------------------------------------------

if (exist ('sparse2') == 3)						    %#ok
    % Use sparse2 in CHOLMOD.  It's faster, allows integer Ai and Aj, and
    % returns the Z matrix as the 2nd output argument.
    if (isempty (Ax))
	Ax = 1 ;
    end
    % numerical matrix
    [A Z] = sparse2 (Ai, Aj, Ax, nrow, ncol) ;
else
    % stick with MATLAB, without CHOLMOD.  This is slower and takes more memory.
    Ai = double (Ai) ;
    Aj = double (Aj) ;
    if (isempty (Ax))
	% pattern-only matrix
	A = spones (sparse (Ai, Aj, 1, nrow, ncol)) ;
	Z = sparse (nrow, ncol) ;
    else
	% numerical matrix
	A = sparse (Ai, Aj, Ax, nrow, ncol) ;
	% determine the pattern of explicit zero entries
	S = spones (sparse (Ai, Aj, 1, nrow, ncol)) ;
	Z = S - spones (A) ;
    end
end

% check for entries in upper part
if (any (mtype (2) == 'shz') & nnz (triu (A,1) > 0))			    %#ok
    fprintf ('entries in upper triangular part of %s matrix ignored\n', mtype);
end

% add the upper triangular part
if (mtype (2) == 's')
    A = A + tril (A,-1).' ;
    Z = Z + tril (Z,-1)' ;
elseif (mtype (2) == 'h')
    A = A + tril (A,-1)' ;
    Z = Z + tril (Z,-1)' ;
elseif (mtype (2) == 'z')
    A = A - tril (A,-1).' ;
    Z = Z + tril (Z,-1)' ;
end


function tcpWithBoost = seanWalshTCP(paramS,doseBinsC,volHistC)
% Sean Walsh TCP model for prostate
% http://dx.doi.org/10.1118/1.4939260
%
% APA, 07/20/2016
% AI, 09/12/16 Modified for use with outcomeModelsGUI

% Get parameters
alpha = 0.25; %paramS.alpha.val;
beta = 0.1008;% paramS.beta.val;
sigmaAlpha = alpha*11.3/100;
sigmaBeta = beta*12.9/100;

n = paramS.numFractions.val;                      % number of fractions

DILparS = paramS.structures.DIL;
dilVolume = DILparS.dilVolume.val;                % percent
pDIL = DILparS.pDIL.val;                          % DIL density
dDIL = DILparS.dDIL.val;                          % dose per fraction to the DIL

PTVparS = paramS.structures.PTV_1;
hypoxicFraction = PTVparS.hypoxicFraction.val;    % percent
OER = PTVparS.OER.val;                            % Oxygen Enhancement Ratio
pCTV = PTVparS.pCTV.val;                          % Prostate density
ctvVolume = PTVparS.ctvVolume.val;                % 36 cm^3 for intermediate risk
                                                  % 72 cm^3 for high risk pts
numSimulations = PTVparS.numSimulations.val;      % number of (alpha,beta) simulations

%Compute mean dose to prostate
prost = calc_meanDose(doseBinsC{2},volHistC{2},1);
%Dose per fraction to the prostate
dProst = prost/n;

% Compute TCP
%Seed the random generator
rng(now,'twister');

%Generate normally distributed, positive aplha and beta
alphaV = alpha + randn(numSimulations*2, 1) * sigmaAlpha;
betaV = beta + randn(numSimulations*2, 1) * sigmaBeta;
alphaV = alphaV(alphaV > 0);
betaV = betaV(betaV > 0);
alphaV = alphaV(1:numSimulations);
betaV = betaV(1:numSimulations);

%Hypoxic cells alpha,beta
alphaPO2 = alphaV / OER;
betaPO2 = betaV / OER^2;

% Total initial clonogen number
N0 = ((100-dilVolume)*pCTV + dilVolume*pDIL) / 100 * ctvVolume;

%Initial number of clonogens in prostate
Nprost = (100-dilVolume)*pCTV / 100 * ctvVolume;

%Initial number of clonogens in DIL
Ndil = dilVolume*pDIL / 100 * ctvVolume;

%Surviving fraction for Prostate
SProstateV = exp(-alphaV*n*dProst -betaV*n*dProst^2);

%Surviving fraction for hypoxic Prostate
ShypoxicProstateV = exp(-alphaPO2*n*dProst -betaPO2*n*dProst^2);

%Surviving fraction for DIL
SdilV = exp(-alphaV*n*dDIL -betaV*n*dDIL^2);

%Surviving fraction for hypoxic DIL
ShypoxicDilV = exp(-alphaPO2*n*dDIL -betaPO2*n*dDIL^2);

%Total surviving clonogens
NumSurvivingV = Nprost*(1-hypoxicFraction)*SProstateV + ...
    Nprost*hypoxicFraction*ShypoxicProstateV + ...
    Ndil*(1-hypoxicFraction)*SdilV +  ...
    Ndil*hypoxicFraction*ShypoxicDilV;

% TCP
TCPv = exp(-NumSurvivingV);

%Record the TCP for this DIL dose
tcpWithBoost = mean(TCPv);

end


function []=panel5disp(n,N,m,p,k,T,d1,d2,d3,d4,d5,Ymat,Xdot,Units,endo,exo,const,Xi,theta_gibbs,theta_median,theta_std,theta_lbound,theta_ubound,sigma_gibbs,sigma_median,D_estimates,gamma_estimates,alpha0,delta0,startdate,enddate,forecast_record,forecast_estimates,Fcperiods,stringdates3,Fstartdate,Fcenddate,Feval,Fcomp,data_endo_c,data_endo_c_lags,data_exo_c,It,Bu,IRF,IRFt,pref,names)

% recover a point estimate (the median) of the VAR coefficients
betatilde=Xi*theta_median;
Btilde=reshape(betatilde,k,N*n);

% check whether the model is stationary
[stationary,eigmodulus]=bear.checkstable(betatilde,N*n,p,k);

% estimate the in-sample evaluation criteria

% obtain a point estimate thetatilde of the structural factors, which is the median
thetatilde=theta_median;
% compute fitted values
Ytilde=full(Xdot*kron(speye(T),thetatilde))';
% reshape for convenience
Ytilde=reshape(Ytilde,T,n,N);
Ymat=reshape(Ymat,T,n,N);

% loop over units
for ii=1:N
% estimate the residuals for this unit
EPS(:,:,ii)=Ymat(:,:,ii)-Ytilde(:,:,ii);

% Compute then the sum of squared residuals
% compute first the RSS matrix, defined in (1.9.5)
RSS(:,:,ii)=EPS(:,:,ii)'*EPS(:,:,ii);
% retain only the diagonal elements to get the vector of RSSi values
rss(:,:,ii)=diag(RSS(:,:,ii));

% Go on calculating R2
% generate Mbar
Mbar=eye(T)-ones(T,T)/T;
% then compute the TSS matrix, defined in (1.9.8)
TSS(:,:,ii)=Ymat(:,:,ii)'*Mbar*Ymat(:,:,ii);
% generate the R2 matrix in (1.9.9)
R2(:,:,ii)=eye(n)-RSS(:,:,ii)./TSS(:,:,ii);
% retain only the diagonal elements to get the vector of R2 values
r2(:,:,ii)=diag(R2(:,:,ii));

% then calculate the adjusted R2, using (1.9.11)
R2bar(:,:,ii)=eye(n)-((T-1)/(T-k))*(eye(n)-R2(:,:,ii));
% retain only the diagonal elements to get the vector of R2bar values
r2bar(:,:,ii)=diag(R2bar(:,:,ii));

end

% estimate the forecast evaluation criteria
% first note that forecast evaluation can only be conducted if it is activated, and if there is some observable data after the beginning of the forecast
if Feval==1 && Fcomp==1

% generate the elements required for the evaluation
beta_gibbs=Xi*theta_gibbs;
forecast_record=reshape(forecast_record,N*n,1);
forecast_estimates=reshape(forecast_estimates,N*n,1);
data_endo_c=reshape(data_endo_c,Fcperiods,N*n);
data_endo_c_lags=reshape(data_endo_c_lags,p,N*n);

% compute forecast evaluation
[RMSE,MAE,MAPE,Ustat,CRPS_estimates,S1_estimates,S2_estimates]=bear.panelfeval(N*n,p,k,beta_gibbs,sigma_gibbs,forecast_record,forecast_estimates,Fcperiods,data_endo_c,data_endo_c_lags,data_exo_c,const,It,Bu);

end

% start displaying and saving the general results

% preliminary task: create and open the txt file used to save the results

filelocation=fullfile(pref.results_path, [pref.results_sub '.txt']);
fid=fopen(filelocation,'wt');

% print toolbox header

fprintf('%s\n','');
fprintf(fid,'%s\n','');

% print the list of contributors
bear.printcontributors(fid);

% print then estimation results

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

toolboxinfo='BEAR toolbox estimates';
fprintf('%s\n',toolboxinfo);
fprintf(fid,'%s\n',toolboxinfo);

time=clock;
datestring=datestr(time);
dateinfo=['Date: ' datestring(1,1:11) '   Time: ' datestring(1,13:17)];
fprintf('%s\n',dateinfo);
fprintf(fid,'%s\n',dateinfo);

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

VARtypeinfo='Panel VAR: structural factor (static)';
fprintf('%s\n',VARtypeinfo);
fprintf(fid,'%s\n',VARtypeinfo);

if IRFt==1
SVARinfo='structural decomposition: none';
fprintf('%s\n',SVARinfo);
fprintf(fid,'%s\n',SVARinfo);
elseif IRFt==2
SVARinfo='structural decomposition: choleski factorisation';
fprintf('%s\n',SVARinfo);
fprintf(fid,'%s\n',SVARinfo);
elseif IRFt==3
SVARinfo='structural decomposition: triangular factorisation';
fprintf('%s\n',SVARinfo);
fprintf(fid,'%s\n',SVARinfo);
end

temp='units: ';
for ii=1:N
temp=[temp ' ' Units{ii,1} ' '];
end
unitinfo=temp;
fprintf('%s\n',unitinfo);
fprintf(fid,'%s\n',unitinfo);

temp='endogenous variables: ';
for ii=1:n
temp=[temp ' ' endo{ii,1} ' '];
end
endoinfo=temp;
fprintf('%s\n',endoinfo);
fprintf(fid,'%s\n',endoinfo);

temp='exogenous variables: ';
if const==0 && m==0
temp=[temp ' none'];
elseif const==1 && m==1
temp=[temp ' constant '];
elseif const==0 && m>0
   for ii=1:m-1
   temp=[temp ' ' exo{ii,1} ' '];
   end
elseif const==1 && m>1
temp=[temp ' constant '];
   for ii=1:m-1
   temp=[temp ' ' exo{ii,1} ' '];
   end
end
exoinfo=temp;
fprintf('%s\n',exoinfo);
fprintf(fid,'%s\n',exoinfo);

sampledateinfo=['estimation sample: ' startdate '-' enddate];
fprintf('%s\n',sampledateinfo);
fprintf(fid,'%s\n',sampledateinfo);

samplelengthinfo=['sample size (omitting initial conditions): ' num2str(T)];
fprintf('%s\n',samplelengthinfo);
fprintf(fid,'%s\n',samplelengthinfo);

laginfo=['number of lags included in regression: ' num2str(p)];
fprintf('%s\n',laginfo);
fprintf(fid,'%s\n',laginfo);

hyperparam1='hyperparameters:';
fprintf('%s\n',hyperparam1);
fprintf(fid,'%s\n',hyperparam1);

hyperparam2=['IG shape on residual variance (alpha0):       ' num2str(alpha0)];
fprintf('%s\n',hyperparam2);
fprintf(fid,'%s\n',hyperparam2);

hyperparam3=['IG scale on residual variance (delta0):       ' num2str(delta0)];
fprintf('%s\n',hyperparam3);
fprintf(fid,'%s\n',hyperparam3);

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% display factor estimates

factorinfo=['Structural factors:'];
fprintf('%s\n',factorinfo);
fprintf(fid,'%s\n',factorinfo);

fprintf('%s\n','');
fprintf(fid,'%s\n','');

factorheader=fprintf('%35s %15s %15s %15s %15s\n','','Median','St.dev','Low.bound','Upp.bound');
factorheader=fprintf(fid,'%35s %15s %15s %15s %15s\n','','Median','St.dev','Low.bound','Upp.bound');

% common component

fprintf('%s\n','theta1 (common component)');
fprintf(fid,'%s\n','theta1 (common component)');
values=[theta_median(1,1) theta_std(1,1) theta_lbound(1,1) theta_ubound(1,1)];
fprintf('%-35s %15.3f %15.3f %15.3f %15.3f\n','common component',values);
fprintf(fid,'%-35s %15.3f %15.3f %15.3f %15.3f\n','common component',values);
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% unit component

fprintf('%s\n','theta2 (unit-specific component)');
fprintf(fid,'%s\n','theta2 (unit component)');
for ii=1:d2
values=[theta_median(d1+ii,1) theta_std(d1+ii,1) theta_lbound(d1+ii,1) theta_ubound(d1+ii,1)];
fprintf('%-35s %15.3f %15.3f %15.3f %15.3f\n',['unit ' int2str(ii) ' component'],values);
fprintf(fid,'%-35s %15.3f %15.3f %15.3f %15.3f\n',['unit ' int2str(ii) ' component'],values);
end
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% variable component

fprintf('%s\n','theta3 (variable-specific component)');
fprintf(fid,'%s\n','theta3 (endogenous variable component)');
for ii=1:d3
values=[theta_median(d1+d2+ii,1) theta_std(d1+d2+ii,1) theta_lbound(d1+d2+ii,1) theta_ubound(d1+d2+ii,1)];
fprintf('%-35s %15.3f %15.3f %15.3f %15.3f\n',['variable ' int2str(ii) ' component'],values);
fprintf(fid,'%-35s %15.3f %15.3f %15.3f %15.3f\n',['variable ' int2str(ii) ' component'],values);
end
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% lag component (if applicable)

if d4~=0
fprintf('%s\n','theta4 (lag-specific component)');
fprintf(fid,'%s\n','theta4 (lag component)');
for ii=1:d4
values=[theta_median(d1+d2+d3+ii,1) theta_std(d1+d2+d3+ii,1) theta_lbound(d1+d2+d3+ii,1) theta_ubound(d1+d2+d3+ii,1)];
fprintf('%-35s %15.3f %15.3f %15.3f %15.3f\n',['lag ' int2str(ii) ' component'],values);
fprintf(fid,'%-35s %15.3f %15.3f %15.3f %15.3f\n',['lag ' int2str(ii) ' component'],values);
end
fprintf('%s\n','');
fprintf(fid,'%s\n','');
end

% exogenous component (if applicable)

if d5~=0
fprintf('%s\n','theta5 (exogenous variable component)');
fprintf(fid,'%s\n','theta5 (exogenous component)');
% initiate equation count
eqcount=0;
% initiate exogenous count
exocount=0;
for ii=1:d5
   if exocount==m
   exocount=0;
   end
   if exocount==0
   eqcount=eqcount+1;
   end
exocount=exocount+1;
values=[theta_median(d1+d2+d3+d4+ii,1) theta_std(d1+d2+d3+d4+ii,1) theta_lbound(d1+d2+d3+d4+ii,1) theta_ubound(d1+d2+d3+d4+ii,1)];
fprintf('%-35s %15.3f %15.3f %15.3f %15.3f\n',['equation ' int2str(eqcount) ', exogenous ' int2str(exocount) ' component'],values);
fprintf(fid,'%-35s %15.3f %15.3f %15.3f %15.3f\n',['equation ' int2str(eqcount) ', exogenous ' int2str(exocount) ' component'],values);
end
fprintf('%s\n','');
fprintf(fid,'%s\n','');
end

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% display VAR stability results
eigmodulus=reshape(eigmodulus,p,N*n);
stabilityinfo1=['Roots of the characteristic polynomial (modulus):'];
fprintf('%s\n',stabilityinfo1);
fprintf(fid,'%s\n',stabilityinfo1);
for jj=1:p
temp=num2str(eigmodulus(jj,1),'%.3f');
   for kk=2:N*n
   temp=[temp,'  ',num2str(eigmodulus(jj,kk),'%.3f')];
   end
fprintf('%s\n',temp);
fprintf(fid,'%s\n',temp);
end
if stationary==1;
stabilityinfo2=['No root lies outside the unit circle.'];
stabilityinfo3=['The estimated VAR model satisfies the stability condition'];
fprintf('%s\n',stabilityinfo2);
fprintf(fid,'%s\n',stabilityinfo2);
fprintf('%s\n',stabilityinfo3);
fprintf(fid,'%s\n',stabilityinfo3);
else
stabilityinfo2=['Warning: at leat one root lies on or outside the unit circle.'];
stabilityinfo3=['The estimated VAR model will not be stable'];
end

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% display posterior for sigma
% reshape sigma
sigma_median=reshape(sigma_median,N*n,N*n);
% start displaying
sigmainfo=['sigma (residual covariance matrix): posterior estimates'];
fprintf('%s\n',sigmainfo);
fprintf(fid,'%s\n',sigmainfo);
% calculate the (integer) length of the largest number in sigma, for formatting purpose
width=length(sprintf('%d',floor(max(abs(bear.vec(sigma_median))))));
% add a separator, a potential minus sign, and three digits (total=5) to obtain the total space for each entry in the matrix
width=width+5;
for ii=1:N*n
temp=[];
   for jj=1:N*n
   % convert matrix entry into string
   number=num2str(sigma_median(ii,jj),'% .3f');
      % pad potential missing blanks
      while numel(number)<width
      number=[' ' number];
      end
   number=[number '  '];
   temp=[temp number];
   end
fprintf('%s\n',temp);
fprintf(fid,'%s\n',temp);
end

fprintf('%s\n','');
fprintf(fid,'%s\n','');

% then display the results for D and gamma, if a structural decomposition was selected

if IRF==1 && IRFt~=1
svarinfo1=['D (structural decomposition matrix): posterior estimates'];
fprintf('%s\n',svarinfo1);
fprintf(fid,'%s\n',svarinfo1);

% recover D
D=reshape(D_estimates,N*n,N*n);
% calculate the (integer) length of the largest number in D, for formatting purpose
width=length(sprintf('%d',floor(max(abs(bear.vec(D))))));
% add a separator, a potential minus sign and three digits (total=5) to obtain the total space for each entry in the matrix
width=width+5;
for ii=1:N*n
temp=[];
   for jj=1:N*n
   % convert matrix entry into string
   number=num2str(D(ii,jj),'% .3f');
      % pad potential missing blanks
      while numel(number)<width
      number=[' ' number];
      end
   number=[number '  '];
   temp=[temp number];
   end
fprintf('%s\n',temp);
fprintf(fid,'%s\n',temp);
end

fprintf('%s\n','');
fprintf(fid,'%s\n','');

svarinfo2=['gamma (structural disturbances covariance matrix): posterior estimates'];
fprintf('%s\n',svarinfo2);
fprintf(fid,'%s\n',svarinfo2);

% recover gamma
gamma=reshape(gamma_estimates,N*n,N*n);
% calculate the (integer) length of the largest number in D, for formatting purpose
width=length(sprintf('%d',floor(max(abs(bear.vec(D))))));
% add a separator, a potential minus sign and three digits (total=5) to obtain the total space for each entry in the matrix
width=width+5;
for ii=1:N*n
temp=[];
   for jj=1:N*n
   % convert matrix entry into string
   number=num2str(gamma(ii,jj),'% .3f');
      % pad potential missing blanks
      while numel(number)<width
      number=[' ' number];
      end
   number=[number '  '];
   temp=[temp number];
   end
fprintf('%s\n',temp);
fprintf(fid,'%s\n',temp);
end

end

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% finally display in-sample and forecast evaluation measures
% if forecast evaluation is activated and possible, display the results
if Feval==1 && Fcomp==1
bear.panel5fprint(Units,N,n,endo,rss,r2,r2bar,RMSE,MAE,MAPE,Ustat,CRPS_estimates,S1_estimates,S2_estimates,stringdates3,Fstartdate,Fcenddate,Fcperiods,fid);

% if forecast evaluation is activated but not possible, return a message to signal it
elseif Feval==1 && Fcomp==0

finfo1=['Forecast evaluation cannot be conducted.'];
fprintf('%s\n',finfo1);
fprintf(fid,'%s\n',finfo1);
finfo2=['Forecasts start in ' Fstartdate ', while observable data is available only until ' names{end,1} '.'];
fprintf('%s\n',finfo2);
fprintf(fid,'%s\n',finfo2);
finfo3=['To obtain forecast evaluation, the forecast start date must be anterior to the end of the data set.'];
fprintf('%s\n',finfo3);
fprintf(fid,'%s\n',finfo3);

% if forecast evaluation is not activated altogether, do not do anything

end


function [I1,I2] = hmxSubdivide(X,dim)
%+========================================================================+
%|                                                                        |
%|         OPENHMX - LIBRARY FOR H-MATRIX COMPRESSION AND ALGEBRA         |
%|           openHmx is part of the GYPSILAB toolbox for Matlab           |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal (c) 2017-2018.                             |
%| PROPERTY  : Centre de Mathematiques Appliquees, Ecole polytechnique,   |
%| route de Saclay, 91128 Palaiseau, France. All rights reserved.         |
%| LICENCE   : This program is free software, distributed in the hope that|
%| it will be useful, but WITHOUT ANY WARRANTY. Natively, you can use,    |
%| redistribute and/or modify it under the terms of the GNU General Public|
%| License, as published by the Free Software Foundation (version 3 or    |
%| later,  http://www.gnu.org/licenses). For private use, dual licencing  |
%| is available, please contact us to activate a "pay for remove" option. |
%| CONTACT   : matthieu.aussal@polytechnique.edu                          |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : hmxSubdivide.m                                |
%|    #    |   VERSION    : 0.40                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal                               |
%|  ( # )  |   CREATION   : 14.03.2017                                    |
%|  / 0 \  |   LAST MODIF : 14.03.2018                                    |
%| ( === ) |   SYNOPSIS   : Subdivide particles with median repartition   |
%|  `---'  |                                                              |
%+========================================================================+

% Sort data on largest dimension
[~,I] = sort(X(:,dim));

% Equal repartition
I1 = I(1:floor(end/2));
I2 = I(floor(end/2)+1:end);
end