function PhasePot_2D_GUI_SDJ()
%--------------------------------------------------%
% PHASE POTRAIT MODEL BY SVEND STEFFENSEN 03/03/2014
% TO CHANGE GRID RESOLUTION AND/OR PLACEMENT AND/OR SHAPE - CHANGE x_min/x_step/x_max AND/OR y_min/y_step/y_max
% TO CHANGE INITIAL CONDITIONS PLACEMENT - CHANGE x_init AND/OR y_init
% IF TRAJECTORY DO NOT SETTLED ON EXPECTED POINT/ORBIT - TRY INCREASING t_max
% HOPE YOU ENJOY THE CODE!

% UPDATED 2016
% ELIMINATED NEED FOR SYMBOLIC TOOL PACKAGE
% ADDED DEFAULT VALUES FOR FAST USE
% UPDATED 2018
% ADDED A "Save figure" PUSHBUTTON THAT ALLOWS EXTRACTION
% OF THE PHASEPLOT FROM THE GUI FOR SAVING/PRINTING
%--------------------------------------------------%

% CLEARS UP MATLAB
close all
clear all
clc

% CREATE AND THEN HIDE THE GUI AS IT IS BEING CONSTRUCTED
f = figure('Visible','off','Position',[360,500,450,285]);

% COMMON OFFSET FOR GROUPED COMPONENT
Mul_off_y = -40;
Mul_off_x = 20;
Mul2_off_y = 0;
Mul2_off_x = 20;


% CONSTRUCT THE GUI COMPONENTS
%____________________________________________________
% AXES
axes1 = axes('Units','pixels','Position',[220,40,220,220],'Tag','axes1');
xlabel('$\bf{x}$','interpreter','latex','FontSize',16);
ylabel('$\bf{y}$','interpreter','latex','FontSize',16);
title('Phase Potrait','FontWeight','Bold')

% ACTUAL CONTROLLER OBJECTS
apply_points_pushbutton = uicontrol('Style','pushbutton',...
    'String','Insert Points/Redraw Grid','Tag','papply','Position',[15,20,115,35],...
    'Callback',{@apply_points_pushbutton_Callback},'Tooltipstring','Applies points to selected vector plane');

xdot_edit = uicontrol('Style','edit',...
    'String','','Tag','xdot','Position',[15+Mul2_off_x,220+Mul2_off_y,50,15],...
    'Callback',{@xdot_edit_Callback},'Tooltipstring','Expression for f(x,y)=\dot{x}');

ydot_edit = uicontrol('Style','edit',...
    'String','','Tag','ydot','Position',[93+Mul2_off_x,220++Mul2_off_y,50,15],...
    'Callback',{@ydot_edit_Callback},'Tooltipstring','Expression for g(x,y)=\dot{y}');

yval_min_edit = uicontrol('Style','edit',...
    'String','','Tag','ymin','Position',[15+Mul_off_x,220+Mul_off_y,20,15],...
    'Callback',{@yval_min_edit_Callback},'Tooltipstring','Min grid value of y',...
    'String','-2','Value',-2);

yval_max_edit = uicontrol('Style','edit',...
    'String','','Tag','ymax','Position',[115+Mul_off_x,220+Mul_off_y,20,15],...
    'Callback',{@yval_max_edit_Callback},'Tooltipstring','Max grid value of y',...
    'String','2','Value',2);

yval_step_edit = uicontrol('Style','edit',...
    'String','','Tag','ystep','Position',[65+Mul_off_x,220+Mul_off_y,20,15],...
    'Callback',{@yval_step_edit_Callback},'Tooltipstring','Step grid value of y',...
    'String','0.1','Value',0.1);

xval_min_edit = uicontrol('Style','edit',...
    'String','','Tag','xmin','Position',[15+Mul_off_x,170+Mul_off_y,20,15],...
    'Callback',{@xval_min_edit_Callback},'Tooltipstring','Min grid value of x',...
    'String','-2','Value',-2);

xval_max_edit = uicontrol('Style','edit',...
    'String','','Tag','xmax','Position',[115+Mul_off_x,170+Mul_off_y,20,15],...
    'Callback',{@xval_max_edit_Callback},'Tooltipstring','Max grid value of x',...
    'String','2','Value',2);

xval_step_edit = uicontrol('Style','edit',...
    'String','','Tag','xstep','Position',[65+Mul_off_x,170+Mul_off_y,20,15],...
    'Callback',{@xval_step_edit_Callback},'Tooltipstring','Step grid value of x',...
    'String','0.1','Value',0.1);

xval_init_edit = uicontrol('Style','edit',...
    'String','','Tag','xinit','Position',[15+Mul_off_x,120+Mul_off_y,20,15],...
    'Callback',{@xval_init_edit_Callback},'Tooltipstring','Initial x-value to solve from');

yval_init_edit = uicontrol('Style','edit',...
    'String','','Tag','yinit','Position',[65+Mul_off_x,120+Mul_off_y,20,15],...
    'Callback',{@yval_init_edit_Callback},'Tooltipstring','Initial y-value to solve from');

tmax_edit = uicontrol('Style','edit',...
    'String','','Tag','tmax','Position',[115+Mul_off_x,120+Mul_off_y,20,15],...
    'Callback',{@tmax_edit_Callback},'Tooltipstring','Amount of time steps to solve','Value',50);


click_radio = uicontrol('Style','radiobutton',...
    'String','Mouse on/off','Tag','click','Position',[135,20,60,15],...
    'Callback',{@click_radio_Callback},'Tooltipstring','Activate to set point by Mouse',...
    'BackgroundColor',[0.8 0.8 0.8]);

spread_radio = uicontrol('Style','radiobutton',...
    'String','Spread on/off','Tag','spread','Position',[135,40,60,15],...
    'Callback',{@spread_radio_Callback},'Tooltipstring','Activate to make a small spread of points (useful near stable points/orbits)',...
    'BackgroundColor',[0.8 0.8 0.8]);

live_radio = uicontrol('Style','radiobutton',...
    'String','Live on/off','Tag','live','Position',[135,60,60,15],...
    'Callback',{@live_radio_Callback},'Tooltipstring',...
    sprintf(['Activate to view live solving\n'...
    'WARNING: This can be quite time consuming']),...
    'BackgroundColor',[0.8 0.8 0.8]);

copy_pushbutton = uicontrol('Style','pushbutton',...
    'String','Save figure','Tag','fcopy','Position',[220,10,45,15],...
    'Callback',{@copy_pushbutton_Callback},'Tooltipstring','Copies current view to seperate figure for printing and/or saving');


% ANNOTATIONS AND TEXT
ymin_pos=get(yval_min_edit,'Position');
txt_ymin = annotation(f,'textbox','String','y_{min}','Units','pixels','Position',...
    [ymin_pos(1)-10 ymin_pos(2)-1 ymin_pos(3)*2 ymin_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.6 0.6 0.6]);

ymax_pos=get(yval_max_edit,'Position');
txt_ymax = annotation(f,'textbox','String','y_{max}','Units','pixels','Position',...
    [ymax_pos(1)-10 ymax_pos(2)-1 ymax_pos(3)*2 ymax_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.6 0.6 0.6]);

ystep_pos=get(yval_step_edit,'Position');
txt_ystep = annotation(f,'textbox','String','y_{step}','Units','pixels','Position',...
    [ystep_pos(1)-10 ystep_pos(2)-1 ystep_pos(3)*2 ystep_pos(4)*2.2],...
    'FontWeight','bold','HorizontalAlignment','Center','BackgroundColor',[0.6 0.6 0.6]);

xmin_pos=get(xval_min_edit,'Position');
txt_xmin = annotation(f,'textbox','String','x_{min}','Units','pixels','Position',...
    [xmin_pos(1)-10 xmin_pos(2)-1 xmin_pos(3)*2 xmin_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.7 0.7 0.7]);

xmax_pos=get(xval_max_edit,'Position');
txt_xmax = annotation(f,'textbox','String','x_{max}','Units','pixels','Position',...
    [xmax_pos(1)-10 xmax_pos(2)-1 xmax_pos(3)*2 xmax_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.7 0.7 0.7]);

xstep_pos=get(xval_step_edit,'Position');
txt_xstep = annotation(f,'textbox','String','x_{step}','Units','pixels','Position',...
    [xstep_pos(1)-10 xstep_pos(2)-1 xstep_pos(3)*2 xstep_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.7 0.7 0.7]);

txt_title = annotation(f,'textbox','String','Phase Potrait Plotter 2018','Units','pixels','Position',...
    [0,270,260,15],'HorizontalAlignment','Left','BackgroundColor',get(f,'color'),'EdgeColor','none',...
    'FontWeight','Bold','FontSize',18);

txt_author = annotation(f,'textbox','String','By Svend Bertel Dahl-Jensen','Units','pixels','Position',...
    [350,0,180,15],'HorizontalAlignment','Left','BackgroundColor',get(f,'color'),'EdgeColor','none',...
    'FontWeight','Bold','FontSize',8);

txt_ydot_pos=get(xdot_edit,'Position');
txt_xdot = annotation(f,'textbox','String','$\bf{\dot{x}}(x,y)$','Interpreter','latex','Units','pixels','Position',...
    [txt_ydot_pos(1)-10 txt_ydot_pos(2)-1 txt_ydot_pos(3)*1.25 txt_ydot_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.5 0.5 0.5],'FontSize',16);

txt_ydot_pos=get(ydot_edit,'Position');
txt_ydot = annotation(f,'textbox','String','$\bf{\dot{y}}(x,y)$','Interpreter','latex','Units','pixels','Position',...
    [txt_ydot_pos(1)-10 txt_ydot_pos(2)-1 txt_ydot_pos(3)*1.25 txt_ydot_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.5 0.5 0.5],'FontSize',16);

xinit_pos=get(xval_init_edit,'Position');
txt_xinit = annotation(f,'textbox','String','x_{init}','Units','pixels','Position',...
    [xinit_pos(1)-10 xinit_pos(2)-1 xinit_pos(3)*2 xinit_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.9 0.9 0.9]);

yinit_pos=get(yval_init_edit,'Position');
txt_yinit = annotation(f,'textbox','String','y_{init}','Units','pixels','Position',...
    [yinit_pos(1)-10 yinit_pos(2)-1 yinit_pos(3)*2 yinit_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.9 0.9 0.9]);

tmax_pos=get(tmax_edit,'Position');
txt_tmax = annotation(f,'textbox','String','t_{max}','Units','pixels','Position',...
    [tmax_pos(1)-10 tmax_pos(2)-1 tmax_pos(3)*2 tmax_pos(4)*2.2],'HorizontalAlignment',...
    'Center','FontWeight','bold','BackgroundColor',[0.9 0.9 0.9]);

txt_mouse_helper = annotation(f,'textbox','String',sprintf(['Click on plot to save point a mouse\n'...
    'Press Enter to solve saved points']),'Units','pixels','Position',...
    [222,240,180,15],'HorizontalAlignment','Left','EdgeColor','none',...
    'FontWeight','Bold','FontSize',7,'BackgroundColor',[1 1 1],'Visible','off',...
    'Tag','mouse_helper');

txt_live_helper = annotation(f,'textbox','String','Drawing, Please Wait...','Units','pixels','Position',...
    [222,240,180,15],'HorizontalAlignment','Left','EdgeColor','none',...
    'FontWeight','Bold','FontSize',8,'BackgroundColor',[1 1 1],'Visible','off',...
    'Tag','live_helper');


% CONSTRUCTS THE MASTER STRUCTURE
Master_Struct = struct(get(axes1,'Tag'),axes1,...
    get(apply_points_pushbutton,'Tag'),apply_points_pushbutton,...
    get(xdot_edit,'Tag'),xdot_edit,get(ydot_edit,'Tag'),ydot_edit,get(yval_min_edit,'Tag'),yval_min_edit,...
    get(yval_max_edit,'Tag'),yval_max_edit,get(yval_step_edit,'Tag'),yval_step_edit,...
    get(xval_min_edit,'Tag'),xval_min_edit,get(xval_max_edit,'Tag'),xval_max_edit,get(xval_step_edit,'Tag'),...
    xval_step_edit,get(click_radio,'Tag'),click_radio,get(xval_init_edit,'Tag'),xval_init_edit,...
    get(yval_init_edit,'Tag'),yval_init_edit,get(tmax_edit,'Tag'),tmax_edit,...
    get(spread_radio,'Tag'),spread_radio,get(live_radio,'Tag'),live_radio,...
    get(txt_mouse_helper,'Tag'),txt_mouse_helper,get(txt_live_helper,'Tag'),txt_live_helper,get(copy_pushbutton,'Tag'),copy_pushbutton);


% INITIALIZE THE GUI
% CHANGE UNITS TO 'normalized' SO GUI COMPONENTS RESIZE AUTOMATICALLY
set([axes1,apply_points_pushbutton,xdot_edit,ydot_edit,xval_min_edit,...
    xval_max_edit,xval_step_edit,yval_min_edit,...
    yval_max_edit,yval_step_edit,txt_xmin,txt_xmax,txt_xstep...
    txt_ymin,txt_ymax,txt_ystep,txt_title,txt_author,txt_xdot,txt_ydot...
    click_radio,xval_init_edit,yval_init_edit,tmax_edit...
    txt_tmax,txt_xinit,txt_yinit,spread_radio,live_radio...
    txt_mouse_helper,txt_live_helper,copy_pushbutton],'Units','normalized');

% ASSIGN THE NAME OF THE GUI TO APPEAR IN THE WINDOW TITLE
set(f,'Name','Liniar Analysis 1D')
% MOVE THE GUI TO THE CENTER OF THE SCREEN
set(f,'Position',[300 151 706 425])
movegui(f,'center')
%______________________________________________________________
% MAKE THE GUID VISIBLE AFTER CONSTRUCTION
set(f,'Visible','on');



% DEFINE INTERACTION FUNCTIONS WHEN THE USER INTERFACES WITH THE EDITALBE -
% GUI COMPONENENTS, THE FUNCTIONS BELOW ARE NESTED FUNCTION TO MAIN
    function apply_points_pushbutton_Callback(MyOwn,eventdata)
        PhasePot_Eval_2D(Master_Struct)
    end

    function xdot_edit_Callback(MyOwn,eventdata)
        Master_Struct.xdot = get(MyOwn,'String');
    end

    function ydot_edit_Callback(MyOwn,eventdata)
        Master_Struct.ydot = get(MyOwn,'String');
    end


    function xval_step_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function xval_min_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function xval_max_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function yval_step_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function yval_min_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function yval_max_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function click_radio_Callback(MyOwn,eventdata)
        if get(MyOwn,'Value')==1
            set(Master_Struct.xinit,'Visible','off')
            set(Master_Struct.yinit,'Visible','off')
        else
            set(Master_Struct.xinit,'Visible','on')
            set(Master_Struct.yinit,'Visible','on')
        end
    end

    function spread_radio_Callback(MyOwn,eventdata)
    end

    function live_radio_Callback(MyOwn,eventdata)
    end


    function xval_init_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function yval_init_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function tmax_edit_Callback(MyOwn,eventdata)
        set(MyOwn,'Value',str2num(get(MyOwn,'String')));
    end

    function copy_pushbutton_Callback(MyOwn,eventdata)
        % CREATE NEW FIGURE
        figure(2)
        % COPY PHASEPLOT TO FIGURE
        copyobj(Master_Struct.axes1,gcf);
        % RESCALE
        set(gca,'units','pixels')
        set(gcf,'Position',[300 151 425 425]);
        set(gca,'Position',[50,50,350,350]);
        set(gca,'units','normalized')
        % REGRAB FIGURE 1 (GUI)
        figure(1)
    end

end % END OF MAIN FUNCTION




function [] = PhasePot_Eval_2D(Master_Struct)
tic
cla
% MAKES GRID
y1 = (get(Master_Struct.xmin,'Value'):get(Master_Struct.xstep,'Value'):get(Master_Struct.xmax,'Value'));
y2 = (get(Master_Struct.ymin,'Value'):get(Master_Struct.ystep,'Value'):get(Master_Struct.ymax,'Value'));
[x_grid, y_grid] = meshgrid(y1,y2);


% CREATES THE COMBINED DIFFERENTIAL FUNCTION
f1 = @(t,x,y) eval(Master_Struct.xdot);
f2 = @(t,x,y) eval(Master_Struct.ydot);
f = @(t,Y) [f1(t,Y(1),Y(2)); f2(t,Y(1),Y(2))];



% ALLOCATES
u = zeros(size(x_grid));
v = zeros(size(x_grid));

% MAKES BASIS FOR VECTOR PLOT BY FINDNG SOLUTION FOR t=0;
for i = 1:numel(x_grid)
    Y_prime = f(0,[x_grid(i); y_grid(i)]);
    u(i) = Y_prime(1);
    v(i) = Y_prime(2);
end




% PLOTS QUIVER PLOT
%axis auto
quiver(Master_Struct.axes1,x_grid,y_grid,u,v,'r');
xlabel('$\bf{x}$','interpreter','latex','FontSize',16);
ylabel('$\bf{y}$','interpreter','latex','FontSize',16);
title('Phase Potrait','FontWeight','Bold')
axis([get(Master_Struct.xmin,'Value')-2*get(Master_Struct.xstep,'Value')...
    get(Master_Struct.xmax,'Value')+2*get(Master_Struct.xstep,'Value')...
    get(Master_Struct.ymin,'Value')-2*get(Master_Struct.ystep,'Value')...
    get(Master_Struct.ymax,'Value')+2*get(Master_Struct.ystep,'Value')])
%axis tight

% MOUSE INPUT OR PREDEFINED
if get(Master_Struct.click,'Value') ==1
    set(Master_Struct.mouse_helper,'Visible','on');
    [x_init, y_init] = ginput();
    set(Master_Struct.mouse_helper,'Visible','off');
else
    x_init = get(Master_Struct.xinit,'Value');
    y_init = get(Master_Struct.yinit,'Value');
end

% MAKES SPREAD OF GRID
if get(Master_Struct.spread,'Value') == 1
    init_tmp = zeros(length(x_init)*5,2);
    k_cnt=1;
    for k=1:length(x_init)
        init_tmp(k_cnt,:) = [x_init(k) y_init(k)];
        init_tmp(k_cnt+1,:) = [x_init(k)+get(Master_Struct.xstep,'Value') y_init(k)];
        init_tmp(k_cnt+2,:) = [x_init(k)-get(Master_Struct.xstep,'Value') y_init(k)];
        init_tmp(k_cnt+3,:) = [x_init(k) y_init(k)+get(Master_Struct.ystep,'Value')];
        init_tmp(k_cnt+4,:) = [x_init(k) y_init(k)-get(Master_Struct.ystep,'Value')];
        k_cnt=k_cnt+5;
    end
    x_init = init_tmp(:,1);
    y_init = init_tmp(:,2);
end

%TIME FRAME FOR ODE SOLVER
t_min=0;
t_max=get(Master_Struct.tmax,'Value');

% SOLVES USING ODE 45
% x_init AND y_init FORM GRID OF INITIAL CONDITIONS
hold on
for list = 1:length(x_init)
    %for y_list = 1:length(y_init)
        [ts,ys] = ode45(f,[t_min,t_max],[x_init(list),y_init(list)]);
        if get(Master_Struct.live,'Value')==1
            set(Master_Struct.live_helper,'Visible','on');
            for t_int=t_min+1:size(ys,1)
                plot(ys((max(t_int-4,1):t_int),1),ys((max(t_int-4,1):t_int),2),'Tag','live_line','Color',[0 0 1])
                drawnow
                %pause(0.1) % ACTIVATED THIS IF THE TRAJECTORIES ARE SHOWN TO FAST
                delete(findall(Master_Struct.axes1,'Tag','live_line'))
            end
            set(Master_Struct.live_helper,'Visible','off');
        end
        plot(ys(:,1),ys(:,2))
        plot(ys(1,1),ys(1,2),'*','Color',[0 0 0]) % START POINT
        plot(ys(end,1),ys(end,2),'g*') % ENDING POINT
    %end
end
hold off
legend('Vector field','Trajectory','Start point','End point')

toc



end