function varargout = Taylor_GUI(varargin)
% TAYLOR_GUI Application M-file for Taylor_GUI.fig
%    FIG = TAYLOR_GUI launch Taylor_GUI GUI.
%    TAYLOR_GUI('callback_name', ...) invoke the named callback.

% Last Modified by GUIDE v2.0 03-Aug-2002 20:57:52

if nargin == 0  % LAUNCH GUI

	fig = openfig(mfilename,'reuse');

	% Generate a structure of handles to pass to callbacks, and store it. 
	handles = guihandles(fig);
    handles.const_a = 0.0;
    handles.const_r = 1.0;
    handles.degrees = [1 2 3];
    handles.val = 1;
	guidata(fig, handles);
    handles;

    function_popup_Callback(handles.function_popup,[],handles)

	if nargout > 0
		varargout{1} = fig;
	end

elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

	try
		if (nargout)
			[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
		else
			feval(varargin{:}); % FEVAL switchyard
		end
	catch
		disp(lasterr);
	end

end

%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and 
%| sets objects' callback properties to call them through the FEVAL 
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the 
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback.  You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks.  Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.

% --------------------------------------------------------------------
function varargout = function_popup_Callback(h, eventdata, handles, varargin)
val = get(h,'Value');
handles.val = val;
guidata(h,handles); % Save the handles structure after adding data

% --------------------------------------------------------------------
function varargout = constant_a_Callback(h, eventdata, handles, varargin)

constant_a = eval(get(handles.constant_a,'string'));
handles.const_a = constant_a;
guidata(h,handles);
Taylor_GUI('function_popup_Callback',handles.function_popup,[],guidata(handles.function_popup))

% --------------------------------------------------------------------
function varargout = constant_r_Callback(h, eventdata, handles, varargin)

constant_r = eval(get(handles.constant_r,'string'));
handles.const_r = constant_r;
guidata(h,handles);
Taylor_GUI('function_popup_Callback',handles.function_popup,[],guidata(handles.function_popup))

% --------------------------------------------------------------------
function varargout = plot_pushbutton_Callback(h, eventdata, handles, varargin)

val = handles.val;
a = handles.const_a;
r = handles.const_r;
left_end = a-r; right_end = a+r; step = r/100;
x = left_end:step:right_end;
degrees = [1 2 3];
[f0, f1, f2, f3, true_fcn] = calculate_fcn(a,x,val);
t = x-a;
poly(1,:) = f0 + f1*t;
poly(2,:) = poly(1,:) + f2*t.^2;
poly(3,:) = poly(2,:) + f3*t.^3;
error = zeros(size(poly));
for i=1:3
    error(i,:) = true_fcn - poly(i,:);
end
handles.degrees = degrees;
handles.x = x;
handles.poly = poly;
handles.error = error;
handles.true_fcn = true_fcn;

x = handles.x;  % Load data from handles structure
poly = handles.poly;
error = handles.error; 
true_fcn = handles.true_fcn;
axes(handles.TaylorGraphs)
plot(x,poly(1,:),'b--')
hold on
plot(x,poly(2,:),'r-.')
plot(x,poly(3,:),'c:','LineWidth',2)
plot(x,true_fcn,'k')
makeTaylorLegend(handles.TaylorGraphs,handles)
hold off
axes(handles.TaylorErrorGraphs)
plot(x,error(1,:),'b--')
hold on
plot(x,error(2,:),'r-.')
plot(x,error(3,:),'c:','LineWidth',2)
makeTaylorErrorLegend(handles.TaylorErrorGraphs,handles)
hold off
celldata = cellstr(num2str(zeros(12,1)));

celldata(1) = cellstr('    x      f(x)     p1(x)    f(x)-p1(x)    p2(x)     f(x)-p2(x)    p3(x)    f(x)-p3(x)');
for i=2:12
    ii = 1 + 20*(i-2);
    celldata(i) = cellstr(sprintf('%6.3f%10.5f%10.5f%13.3e%10.5f%14.3e%10.5f%13.3e',...
        x(ii),true_fcn(ii),poly(1,ii),error(1,ii),poly(2,ii),error(2,ii),poly(3,ii),error(3,ii)));
end

StringData = char(celldata);
set(handles.output_listbox,'string',StringData)
%set(handles.output_listbox,'string',StringData,'fontname','fixedwidth','fontsize',10)

% --------------------------------------------------------------------
function varargout = file_menu_Callback(h, eventdata, handles, varargin)
if isempty(get(handles.TaylorGraphs,'Children'))
    set(handles.print_submenu,'Enable','off')
    set(handles.output_submenu,'Enable','off')
else
    set(handles.print_submenu,'Enable','on')
    set(handles.output_submenu,'Enable','on')
end

% --------------------------------------------------------------------
function varargout = print_submenu_Callback(h, eventdata, handles, varargin)

h_invisible = figure('visible','off'); 
hax = copyobj(handles.TaylorGraphs,h_invisible);
set(hax,'units',get(0,'defaultaxesunits'),'position',get(0,'defaultaxesposition'))
makeTaylorLegend(hax,handles)
print(h_invisible,'-depsc','taylor_graphs') 
close(h_invisible);

h_invisible = figure('visible','off'); 
hax = copyobj(handles.TaylorErrorGraphs,h_invisible);
set(hax,'units',get(0,'defaultaxesunits'),'position',get(0,'defaultaxesposition'))
makeTaylorErrorLegend(hax,handles)
print(h_invisible,'-depsc','taylor_error_graphs') 
close(h_invisible);
disp('The graphs are stored under the names "taylor_graphs.eps"')
disp('        and "taylor_error_graphs.eps"')

% --------------------------------------------------------------------
function varargout = output_submenu_Callback(h, eventdata, handles, varargin)

% Load data from handles structure
x = handles.x; 
poly = handles.poly;
error = handles.error; 
true_fcn = handles.true_fcn;

fid = fopen('TaylorOutput','w');
fprintf(fid,'    x      f(x)     p1(x)    f(x)-p1(x)    p2(x)     f(x)-p2(x)    p3(x)    f(x)-p3(x)\n');
for i=2:12
    ii = 1 + 20*(i-2);
    fprintf(fid,'%6.3f%10.5f%10.5f%13.3e%10.5f%14.3e%10.5f%13.3e\n',...
        x(ii),true_fcn(ii),poly(1,ii),error(1,ii),poly(2,ii),error(2,ii),poly(3,ii),error(3,ii));
end
fclose(fid);
disp('The table is saved under the name "TaylorOutput"')

% --------------------------------------------------------------------

function varargout = close_submenu_Callback(h, eventdata, handles, varargin)
delete(handles.figure1)

% --------------------------------------------------------------------
function varargout = output_listbox_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function [f0, f1, f2, f3, true_fcn] = calculate_fcn(a,x,val)
% 
% Calculate true function values at x, and calculate function and first, second, 
% and third derivatives at a.

switch val
case 1 % User selected exp(x)
    true_fcn = exp(x);
    expa = exp(a);
    f0 = expa;
    f1 = expa;
    f2 = expa/2;
    f3 = expa/6;
case 2 % User selected cos(x)
    true_fcn = cos(x);
    f0 = cos(a);
    f1 = -sin(a);
    f2 = -cos(a)/2;
    f3 = sin(a)/6;
case 3 % User selected sin(x)
    true_fcn = sin(x);
    f0 = sin(a);
    f1 = cos(a);
    f2 = -sin(a)/2;
    f3 = -cos(a)/6;   
case 4 % User selected log(x)
    f0 = log(a);
    f1 = 1/a;
    f2 = -.5/(a*a);
    f3 = 1/(3*a*a*a);
    true_fcn = zeros(size(x));
    for i=1:length(x)
        if x(i) > 0
            true_fcn(i) = log(x(i));
        else
            true_fcn(i) = 0;
        end
    end
case 5 % User selected atan(x)
    true_fcn = atan(x);
    f0 = atan(a);
    temp1 = 1+a*a;
    f1 = 1/temp1;
    f2 = -a/temp1^2;
    f3 = (3*a*a-1)/(3*temp1^3);
case 6 % User selected exp(-x)*cos(x)
    true_fcn = exp(-x).*cos(x);
    temp1 = exp(-a);
    temp2 = cos(a);
    temp3 = sin(a);
    f0 = temp1*temp2;
    f1 = -temp1*(temp2+temp3);
    f2 = temp1*temp3;
    f3 = (1/3)*temp1*(-temp3+temp2);
case 7 % User selected sqrt(x)
    true_fcn = sqrt(x);
    f0 = sqrt(a);
    f1 = 0.5/f0;
    f2 = -0.125/(a*f0);
    f3 = 0.0625/(a*a*f0);
case 8 % User selected exp(cos(x))
    true_fcn = exp(cos(x));
    f0 = exp(cos(a));
    f1 = -sin(a)*f0;
    f2 = 0.5*f0*(1-cos(a)-cos(a)^2);
    f3 = (1/6)*f0*cos(a)*sin(a)*(3+cos(a));
case 9 % User selected log(1+exp(x))
    true_fcn = log(1+exp(x));
    temp = exp(a);
    f0 = log(1+temp);
    f1 = temp/(1+temp);
    f2 = 0.5*temp/(1+temp)^2;
    f3 = -(1/6)*temp*(-1+temp)/(1+temp)^3;
end

% --------------------------------------------------------------------
function makeTaylorLegend(hax,handles)
legend(hax, ...
    strcat('Degree = ',num2str(handles.degrees(1))), ...
    strcat('Degree = ',num2str(handles.degrees(2))),...
    strcat('Degree = ',num2str(handles.degrees(3))),'True function','Location','Best')

% --------------------------------------------------------------------
function makeTaylorErrorLegend(hax,handles)
legend(hax, ...
    strcat('Degree = ',num2str(handles.degrees(1))), ...
    strcat('Degree = ',num2str(handles.degrees(2))),...
    strcat('Degree = ',num2str(handles.degrees(3))),'Location','Best')

