function xppolytl(x,y,n,alpha)
%XPPOLYTL Interactively fits a polynomial to noisy data.
%	Adapted from POLYTOOL in the Statistics Toolbox.
	
%	B.A. Jones 3-15-93
%	Adapted for Expo by Ned Gulley
%	Copyright (c) 1984-94 by The MathWorks, Inc.

global X_FIELD Y_FIELD1 Y_FIELD2 Y_FIELD3 WITNESSLINE YVERTICAL;
global NEWX NEWY BETA DELTAY STRUCTURE CURSORSTATE YENDPTS MAXX MINX;
global XVALUES YVALUES DEGREE ALPHA POPUP FITLINE AXISP CRIT BCOLOR;

if nargin<1,
    action='start';
elseif isstr(x),
    action=x;
end

if strcmp(action,'start')

% Since we're using a lot of global variables here, we want to
% make sure that if the user tries to run this again, they will
% be directed to any already open window.
[existFlag,figNumber]=figflag('Polynomial Plotting Tool',1);
if existFlag,
    figure(figNumber);
    return
end 

figNumber=figure( ...
    'Name','Polynomial Plotting Tool', ...
    'NumberTitle','off', ...
    'BackingStore','off');

x=[-1:.1:-0.2 .8:.1:1];
pn=conv([1 randn],conv([1 randn],[1 randn]));
y=polyval(pn,x);
y=y+randn(size(y))*max(abs(y))/5;
XVALUES = x;
YVALUES = y;

if nargin < 3, 
    DEGREE = 1;
else
    DEGREE = n;
end

if nargin < 4, 
    ALPHA = 0.05;
else
    ALPHA = alpha;
end

CRIT = tinv(1 - ALPHA/2,max(size(y)) - DEGREE - 1);

% Set positions of graphic objects
%AXISP   = [.21 .15 .75 .70];
AXISP   = [0.10 0.10 0.55 0.80];

MAXX = max(XVALUES);
MINX = min(XVALUES);
rangex = MAXX - MINX;
MAXX = MAXX + 0.025 * rangex;
MINX = MINX - 0.025 * rangex;

[BETA STRUCTURE] = polyfit(XVALUES,YVALUES,DEGREE);
xfit = linspace(MINX,MAXX,40)';
yfit = polyval(BETA,xfit);

CURSORSTATE = 'arrow';
YENDPTS = get(gca,'YLim');
YVERTICAL = linspace(YENDPTS(1),YENDPTS(2))';
xvert = ones(size(YVERTICAL)) * (MAXX+MINX)/2;
NEWX  = xvert(1);
NEWY = polyval(BETA,NEWX,STRUCTURE);

BCOLOR = [0.5 0.5 0.5];

%===================================
% Information for all buttons
top=0.95;
bottom=0.05;
labelColor=[0.8 0.8 0.8];
btnWid=0.20;
btnHt=0.07;
right=0.95;
left=right-btnWid;
% Spacing between the button and the next command's label
spacing=0.03;

%====================================
% The CONSOLE frame
frmBorder=0.02;
frmPos=[left-frmBorder bottom-frmBorder btnWid+2*frmBorder (top-bottom)+2*frmBorder];
h=uicontrol( ...
    'Style','frame', ...
    'Units','normalized', ...
    'Position',frmPos, ...
    'BackgroundColor',[0.5 0.5 0.5]);

% Define all uicontrol locations
newDataBtnPos=[left top-btnHt btnWid btnHt];
popupField= [left top-btnHt-(btnHt+spacing) btnWid btnHt];
xfieldp = [left top-btnHt-(btnHt+spacing)*3 btnWid btnHt];
yfieldp = [left top-btnHt-(btnHt+spacing)*6 btnWid btnHt];
%xfieldp=[0.50 .02 .15 .05];
%yfieldp = [.01 .45 .13 .04];
infoBtnPos=[left bottom+btnHt+spacing btnWid btnHt];
closeBtnPos=[left bottom btnWid btnHt];


% Install all uicontrols
NEWDATA=uicontrol('Style','pushbutton', ...
	'Units','normalized', ...
	'Position',newDataBtnPos, ...
	'String','New Data', ...
	'Callback','xppolytl(''newdata'');');

POPUP=uicontrol('Style','Popup','String',...
    'Linear|Quadratic|Cubic|Quartic|Quintic',...
        'Position',popupField,'Units','normalized',...
        'CallBack','xppolytl(''change_degree'')');

X_FIELD=uicontrol('Style','edit','Position',xfieldp,...
         'Units','normalized','String',num2str(NEWX),...
         'BackgroundColor','white',...
         'CallBack','xppolytl(''edittext'')');

Y_FIELD1=uicontrol('Style','text','Units','normalized',...
'Position',yfieldp + [0 2*btnHt 0 0],'String',num2str(NEWY),...
         'ForegroundColor','white','BackgroundColor',BCOLOR);

Y_FIELD2=uicontrol('Style','text','Units','normalized',...
'Position',yfieldp + [0 btnHt 0 0],'String',' +/-',...
         'ForegroundColor','white','BackgroundColor',BCOLOR);

Y_FIELD3=uicontrol('Style','text','Units','normalized',...
'Position',yfieldp,'String',num2str(DELTAY),...
'ForegroundColor','white','BackgroundColor',BCOLOR);

X_TEXT=uicontrol('Style','text','Position',xfieldp + [0 btnHt 0 0],...
        'Units','normalized','BackgroundColor',BCOLOR,...
        'ForegroundColor','white','String','X Value');
        
Y_TEXT=uicontrol('Style','text','Position',yfieldp + [0 3*btnHt 0 0],...
        'Units','normalized','BackgroundColor',BCOLOR,...
        'ForegroundColor','white','String','Y Value');

set(POPUP,'Value',DEGREE);
    
info_button = uicontrol('Style','Pushbutton','Position',infoBtnPos,...
'Units','normalized','Callback','xppolytl(''info'')','String','Info');

close_button = uicontrol('Style','Pushbutton','Position',closeBtnPos,...
'Units','normalized','Callback','xppolytl(''done'')','String','Close');

xppolytl('setdata');

% Finished with plot startup function.

elseif strcmp(action,'info'),
    ttlStr=get(gcf,'Name');
    hlpStr= ...                                                 
        ['                                                   '  
         ' This demo shows a least-squares fit to some       '  
         ' (x,y) data generated using a cubic polynomial     '  
         ' with added random noise.                          '  
         '                                                   '  
         ' The graph is a prediction plot that provides an   '  
         ' Nth degree polynomial curve fit to the (x,y) data.'  
         ' The red curves correspond to 95% confidence       '  
         ' intervals. Notice that the confidence intervals   '  
         ' tends to bulge in the region for which there is   '  
         ' no data.                                          '  
         '                                                   '  
         ' You can drag the dotted white witness line and    '  
         ' watch the predicted values update                 '  
         ' simultaneously. Alternatively, you can get a      '  
         ' specific prediction by typing the "X" value into  '  
         ' an editable text field. A pop-up menu at the top  '  
         ' allows you to change the degree of the            '  
         ' polynomial fit.                                   '];
    helpfun(ttlStr,hlpStr);                                     

elseif strcmp(action,'newdata'),

    x=[-1:.1:-0.2 .8:.1:1];
    pn=conv([1 randn],conv([1 randn],[1 randn]));
    y=polyval(pn,x);
    y=y+randn(size(y))*max(abs(y))/5;
    XVALUES = x;
    YVALUES = y;

    MAXX = max(XVALUES);
    MINX = min(XVALUES);
    rangex = MAXX - MINX;
    MAXX = MAXX + 0.025 * rangex;   
    MINX = MINX - 0.025 * rangex;

    [BETA STRUCTURE] = polyfit(XVALUES,YVALUES,DEGREE);
    xfit = linspace(MINX,MAXX,40)';
    yfit = polyval(BETA,xfit);

    xppolytl('setdata');

elseif strcmp(action,'motion'),
    if y == 0,
        cp = get(gca,'CurrentPoint');
        cx = cp(1,1);
        cy = cp(1,2);
        fuzz = 0.01 * (MAXX - MINX);
        online = cy > YENDPTS(1) & cy < YENDPTS(2) & cx > NEWX - fuzz & cx < NEWX + fuzz;
        if online & strcmp(CURSORSTATE,'arrow'),
            CURSORSTATE = 'crosshair';
            set(gcf,'Pointer',CURSORSTATE);
        elseif ~online & strcmp(CURSORSTATE,'crosshair'),
            CURSORSTATE = 'arrow';
            set(gcf,'Pointer',CURSORSTATE);
        end
    else
        cp = get(gca,'CurrentPoint');
        NEWX=cp(1,1);
        if NEWX > MAXX
            NEWX = MAXX;
        end
        if NEWX < MINX
            NEWX = MINX;
        end
        [NEWY DELTAY]=polyval(BETA,NEWX,STRUCTURE);
        DELTAY = DELTAY*CRIT;
    set(X_FIELD,'String',num2str(NEWX));
        set(Y_FIELD1,'String',num2str(NEWY));
        set(Y_FIELD3,'String',num2str(DELTAY));
    set(WITNESSLINE,'XData',NEWX*ones(size(YVERTICAL)));
    end

elseif strcmp(action,'down'),
    set(gcf,'WindowButtonMotionFcn','xppolytl(''motion'',1)');
    set(gcf,'WindowButtonUpFcn','xppolytl(''up'')');

elseif strcmp(action,'up'),
    set(gcf,'WindowButtonMotionFcn','xppolytl(''motion'',0)');
    set(gcf,'WindowButtonUpFcn','');

elseif strcmp(action,'setdata')
    cla
    [BETA STRUCTURE] = polyfit(XVALUES,YVALUES,DEGREE);
    xfit = linspace(MINX,MAXX,40)';
    [yfit DELTAY]=polyval(BETA,xfit,STRUCTURE);
    DELTAY = DELTAY*CRIT;   
    CURSORSTATE = 'arrow';
    set(gcf,'Units','Normalized');
    %h = axes;
    %set(h,'XTick',[],'YTick',[],'Units','Normalized','Position',[0 0 1 1]);
    %set(h,'Color',BCOLOR);

    %nh = axes;
    nh=gca;
    xlabel('X Value');
    ylabel('Y Value');
	%axes(nh);

    set(nh,'NextPlot','add','DrawMode','fast','Box','on');
    set(nh,'Position',AXISP,'Color','k');

    set(nh,'XLim',[MINX MAXX]);
	FITLINE = plot(XVALUES,YVALUES,'y+',xfit,yfit,'g-',xfit,yfit-DELTAY,'r--',xfit,yfit+DELTAY,'r--');
    YENDPTS = get(nh,'YLim');
    YVERTICAL = linspace(YENDPTS(1),YENDPTS(2))';
    xvert = ones(size(YVERTICAL)) * (MAXX+MINX)/2;
    NEWX  = xvert(1);
    obs = max(size(YVALUES));
    [NEWY DELTAY]=polyval(BETA,NEWX,STRUCTURE);
    DELTAY = DELTAY*CRIT;
    WITNESSLINE = plot(xvert,YVERTICAL,'w--','Erasemode','xor');
    set(WITNESSLINE,'ButtonDownFcn','xppolytl(''down'')');
    set(gcf,'Backingstore','off','WindowButtonMotionFcn','xppolytl(''motion'',0)');

    xppolytl('edittext');

elseif strcmp(action,'edittext'),
    NEWX=str2num(get(X_FIELD,'String'));
    if NEWX > MAXX
        NEWX = MAXX;
        set(X_FIELD,'String',num2str(NEWX));
    end
    if NEWX < MINX
        NEWX = MINX;
        set(X_FIELD,'String',num2str(NEWX));
    end

    [NEWY DELTAY]=polyval(BETA,NEWX,STRUCTURE);
    DELTAY = DELTAY*CRIT;
    set(Y_FIELD1,'String',num2str(NEWY));
    set(Y_FIELD3,'String',num2str(DELTAY));
    set(WITNESSLINE,'XData',NEWX*ones(size(YVERTICAL)),'Ydata',YVERTICAL);

elseif strcmp(action,'change_degree')
DEGREE = get(POPUP,'Value');
CRIT = tinv(1 - ALPHA/2, max(size(YVALUES)) - (DEGREE + 1));
xppolytl('setdata');

elseif strcmp(action,'done'),
    clear global X_FIELD Y_FIELD1 Y_FIELD2 Y_FIELD3 WITNESSLINE YVERTICAL;
    clear global NEWX NEWY BETA DELTAY STRUCTURE CURSORSTATE YENDPTS;
    clear global MAXX MINX CRIT BCOLOR;
    clear global XVALUES YVALUES DEGREE ALPHA POPUP FITLINE AXISP;

    close;
end

