www.gusucode.com > mbcmodels 工具箱 matlab 源码程序 > mbcmodels/mv_stepwise.m

    function varargout=mv_stepwise(Action,varargin)
% MV_STEPWISE Interactive tool for stepwise regression.
% 
% Stepwise GUI tool for use with MBrowser

%  Copyright 2000-2015 The MathWorks, Inc. and Ford Global Technologies, Inc.



switch lower(Action)
case 'create'
   % Create Stepwise Figure
   varargout{1}=i_Create(varargin{:});
case 'update'
   i_Update(varargin{:});
case 'click'
   % Toggle term in and out of model
   % Click on Table Entry or Errorbar
   i_Step(varargin{:});
case 'auto'
   % Minimise PRESS
   % Click on 'Auto' Button
   i_MinPress(varargin{:});
case 'crit'
   % Change Significance Level for Confidence Interval
   % Change Entry in CI editbox
   i_ChangeCrit
case 'radio'
   i_Radio(varargin{:});
case 'vslider'
   i_VSlider
case 'includeall'
   % Include all terms in model
   % Click on 'Include All' Button
   i_IncludeAll(varargin{:});
case 'removeall'
   % Remove all terms from model
   % Click on 'Remove All' Button
   i_RemoveAll(varargin{:});
case 'remove'
   % Remove Statistically Insignificant Terms from model
   % Click on 'Remove' Button
   i_RemoveInsig(varargin{:});
case 'addsig'
   % Add Statistically significant Terms to model
   % Click on 'Add' Button
   i_AddSig(varargin{:});
case 'history'
   % Retrieve Model from History
   % Click on History Points
   i_History(varargin{:})

case 'close'
   % Close Figure and Update Model Results
   i_Close
end


%------------------------------------------------------------------------
% SUBFUNCTION i_Create
%------------------------------------------------------------------------
function table_fig= i_Create(p_mdev,alpha,UpdateFcn)


if nargin<3
    UpdateFcn = '';
end

hFig= findobj(get(0,'Children'),'flat','Tag','stepwisefig');
if ~isempty(hFig)
   hFig=hFig(1);
   table_fig=hFig;
   ud= get(hFig,'UserData');
   % Model for Stepwise
   Model= p_mdev.model;
   
   if ~( strcmp(class(Model),class(ud.Model)) && size(Model,1) == size(ud.Model,1) )
       % create a new stepwise figure
       delete(hFig);
       table_fig= i_Create(p_mdev,alpha,UpdateFcn);
       return
   end
      
   refreshFigure(p_mdev,Model,ud,hFig);
   figure(hFig);
   return
end
   
%=========================================================
% only come in here first time to create the UI
%=========================================================

% since this takes a while - give people a waitbar to look at
wb = xregGui.waitdlg('title', 'Creating Stepwise Figure', 'parent', mvf);

% Model for Stepwise
Model= p_mdev.model;
Yname= p_mdev.name;

% Number of parameters in full model
p=size(Model,1);

% Data is stored in Model Object while in GR.
% Need to determine total number of observations 
Constant = IncludeConst(Model);

% (3,2) element is the df for SST 
Xdata= p_mdev.getdata('X');
Nobs= size(Xdata,1);

alpha=0.05;
% Calculate Critical y values for all possible cases
sigprob = 1 - alpha/2;
df   = 1:max(Nobs,size(Model,1));
crit = i_Calctinv(sigprob,df);

[Model,~,NewPRESS,B]= stepwise(Model);


% Coefficient Table.
% This needs to be Axes/Text based because TeX labels are required

% determine height of table 
units = get(0,'Units');
set(0,'Units','pixels');
screen= get(0,'ScreenSize');
set(0,'Units',units);
Aht= screen(end,4)-200;
fht=max(Aht+100,680); 

rows    = p;
TableSize = [ 65*6 , Aht+25 ];


% Create the figure for the Stepwise GUI
table_fig = xregfigure('Visible','off',...
   'HandleVisibility','callback',...
   'Tag','stepwisefig',...
   'Resize','off',...
   'Name',['Stepwise Regression for ',Yname],...
   'CloseRequestFcn',[mfilename,'(''Close'')']);

% Table for Coefficients and Statistics
Headings = {'Term','Status','B','std B','t','Next PRESS'};

% Table Spacing

% Extra properties
% update  waitbar
wb.Waitbar.value = 0.1;
lbls = labels(Model);

% use biggest label to determine size of text items
[~,pmax]= max(cellfun('prodofsize',lbls));

htmp= uicontrol('Parent',table_fig,...
   'Style','popup',...
   'String',lbls{pmax},...
   'Position',[0 0 63 18],...
   'Visible','off');
hextent= get(htmp,'Extent');
delete(htmp);
rowHt= hextent(4)+6;
hAx = axes('Parent',table_fig);
htmp = text('Parent',hAx,'String',lbls{pmax},'Units','pixels');
hextent= get(htmp,'Extent');
delete(hAx);

% reduce size of GUI when there are fewer terms than screen size
fht = max(min((rows+1)*(rowHt)+100,fht),630);
% add offset for terms
TermsOffset = min(max(hextent(3)-30,0));
apos= [TableSize(1)+TermsOffset+250 100 360 170];
figpos = [1 screen(4)-fht-50 apos(1)+apos(3)+30 fht];
if figpos(3)>screen(3)
    % reduce offset if it makes the figure bigger than the screen
    TermsOffset = min(TermsOffset - (figpos(3)-screen(3)),0);
    apos= [TableSize(1)+TermsOffset+250 100 360 170];
    figpos = [1 screen(4)-fht-50 apos(1)+apos(3)+10 fht];
end


tbl=xregtable(table_fig,...
   'cols.size',65,...
   'rows.size',rowHt,...
   'frame.hborder',[2+TermsOffset 0],...
   'frame.vborder',[2 20],...
   'frame.box','on',...
   'rows.spacing',0,...
   'cols.spacing',0,...
   'cells.defaultbackgroundcolor',[1 1 1],...
   'defaultcelltype','uiemuedit0',...
   'defaultcellformat','%p4.9',...
   'rows.number',rows+1,...
   'cols.number',6,...
   'rows.fixed',1,...
   'cols.fixed',1,...
   'zeroindex',[2 2],...
   'frame.visible','off',...
   'vslider.callback',[mfilename,'(''vslider'')']);

% update  waitbar
wb.Waitbar.value = 0.6;

tbl.redrawmode= 'basic';
if TermsOffset<30
    halign = 'center';
else
    halign = 'right';
end
set(tbl,...
   'cells.rowselection',[1 1],...
   'cells.colselection',[1 6],...
   'cells.type','text',...
   'cells.string',Headings,...
   'cells.rowselection',[1 1],...
   'cells.colselection',[1 1],...
   'cells.HorizontalAlignment',halign,...
   'cells.rowselection',[2 rows+1],...
   'cells.colselection',[1 1],...
   'cells.type','text',...
   'cells.string',lbls,...
   'cells.HorizontalAlignment',halign,...
   'cells.rowselection',[2 rows+1],...
   'cells.colselection',[2 2],...
   'cells.type','uipopupmenu',...
   'cells.string',repmat({{'Always','Never','Step'}},rows,1),...
   'cells.BackGroundColor','w',...
   'cells.HorizontalAlignment','left',...
   'cells.rowselection',[2 rows+1],...
   'cells.colselection',[2 6],...
   'cells.HorizontalAlignment','right')
   
% update  waitbar
wb.Waitbar.value = 0.67;

ud.TermsOrder= termorder(Model)';
Status= getstatus(Model);
tbl(:,1)= Status(ud.TermsOrder);
tbl(0,end).FontWeight= 'bold';


pnl = get(tbl,'panel');
set(pnl,'BorderType', 'none')
[step_axes,bhandles,phandle] = createCIAxes(pnl,p,Model);

% Anova Table and other Stats
Stats= gui_diagstats(Model, 'create',table_fig);
if isa(get(Stats.layout,'LayoutComponent'), 'xregcontainer')
    set(get(Stats.layout,'LayoutComponent'), 'packstatus', 'on');
end
set(Stats.layout,'Visible','on');

% update  waitbar
wb.Waitbar.value = 0.88;

[ud,CIlyt] = createCIControls(alpha,table_fig,ud);


ud.UpdateHistory = @i_UpdateHistory;
% History display
HistPanel = createHistoryAxes(table_fig,Nobs,p);
HistAxes = HistPanel.AxesHandle;

[hLabels,hList] = createHistoryList(p_mdev,table_fig);
[CallBack,BottomLyt] = createButtons(table_fig);

RHScomponents = {HistPanel,...
    [],...
    hLabels,...
    hList,...
    Stats.layout,...
    CIlyt,[]};

MainLyt = xreggridbaglayout(table_fig,...
    'dimension',[9 3],...
    'ColSizes',[-1 30 330],...
    'gapy',1,...
    'Border',[10 10 10 10],...
    'RowSizes',[200,30,15,150,170,20,-1,20,25],...
    'elements',[{tbl},cell(1,7),{BottomLyt},...
    cell(1,9),...
    [RHScomponents,cell(1,2)]],...
    'MergeBlock',{[1 7],[1 1]},...
    'MergeBlock',{[9 9],[1 3]});


% Set up Figure Position here
set(table_fig, ...
   'Position',figpos);
set(table_fig,'ContentHandle',MainLyt);

% Position errorbar plot
VisRows= min(tbl.rows.onscreen-1,p);
tpos = get(tbl,'Position');
ah= tpos(4)-(VisRows+1)*(rowHt);
set(step_axes,'Position',[TableSize(1)+30+TermsOffset ah 180 (VisRows)*(rowHt)],...
    'YLim',[0.5 VisRows+0.5]);

createMenus(table_fig,CallBack);

% update  waitbar
wb.Waitbar.value = 0.91;

% Figure UserData Structure
ud.crit       = crit;
ud.Nobs       = Nobs;
ud.Model      = Model;
ud.OrigModel  = Model;
ud.Constant   = Constant;
ud.p_mdev     = p_mdev;
ud.UpdateFcn  = UpdateFcn;
ud.DoingUpdate = false;
ud.ParentFig  = get(MBrowser,'Figure');
ud.Stats      = Stats;
ud.TermsOrder= termorder(Model)';

ud.Hand.Figure = table_fig;
ud.Hand.Labels = zeros(p,1);
ud.Hand.Table = tbl;
ud.Hand.CIAxes= step_axes;
ud.Hand.Point= phandle;
ud.Hand.Bar  = bhandles;
ud.Hand.HistAxes= HistAxes;
ud.Hand.hList= hList;

% Make Table Text Handles
Status = getstatus(Model);

% Variable Names
tbl(:,end).Enable= 'inactive';

for i=1:3
   s= find(Status(ud.TermsOrder)==i);
   i_DisplayStatus(ud,i,s)
   tbl(s,[0 end]).ButtonDownFcn = [mfilename,'(''click'')'];
   tbl(s,1).CallBack= [mfilename,'(''radio'')'];
end
% Display Initial Results 
set(table_fig,'UserData',ud);

set(table_fig,'Visible','on');
tbl.visible='on';

i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,Model,table_fig,HistAxes);

% update  waitbar
wb.Waitbar.value = 1.0;


% kill the waitbar
delete(wb);

return


%-------------------------------------------
%  SUBFUNCTION  i_Update
%-------------------------------------------
function i_Update(hFig)
ud= get(hFig,'UserData');
if ud.DoingUpdate
    % event was initiated from stepwise UI
    ud.DoingUpdate = false;
else
    m= ud.p_mdev.model;
    
    % Recalcuate old model
    [ud.Model,~,NewPRESS,B]= stepwise(m);
    
    % Update Displays
    i_DisplayResults(ud,NewPRESS,B)
    i_UpdateHistory(NewPRESS,ud.Model,hFig,ud.Hand.HistAxes);
end
set(hFig,'UserData',ud);

%-------------------------------------------
%  SUBFUNCTION  i_CIntervals
%-------------------------------------------
function [Bint,crit]= i_CIntervals(B,ud)
CritVals = ud.crit;
beta= B(:,1);
crit= zeros(size(beta));
df= B(:,3);
intdf= df==fix(df) & df>=1;
crit(intdf)= CritVals(df(intdf));
if ~all(intdf) && ~any(df(~intdf)<10)
	% use linear interpolation for non-integer
	fdf= floor(df(~intdf));
	cdf= ceil(df(~intdf));
	crit(~intdf)= CritVals(fdf)+ (df(~intdf)-fdf)./(cdf-fdf).*(CritVals(cdf)-CritVals(fdf));
elseif ~all(intdf) && any(df(~intdf)<10)
   % except if df <10, when you should recalculate tinv
   alpha= get(ud.CritVal,'UserData')/100;
   sigprob= 1-alpha/2;
   crit(~intdf)=  i_Calctinv(sigprob,df(~intdf));
end
% calculate confidence intervals and tcrit values
Bint= [B(:,1)-crit.*B(:,2) B(:,1)+crit.*B(:,2)];


%------------------------------------------------------------------------
% SUBFUNCTION i_DisplayResults
%------------------------------------------------------------------------
function i_DisplayResults(ud,PRESS,B)
% Local function for writing out all the entries in the Parameter Data Table.

Bint= i_CIntervals(B,ud);

beta= B(:,1);

% round this for the moment
df1=ceil(max(B(:,3)));
df2=floor(min(B(:,3)));

sig= get(ud.CritVal,'UserData');
if df1>0
   t1= ud.crit(df1);
   set(ud.CritVal1,'String',sprintf('t(%.2g,%1d) = %.3f',sig/200,df1,t1))
else
   set(ud.CritVal1,'String','')
end   
if df2>0
   t2= ud.crit(df2);
   set(ud.CritVal2,'String',sprintf('t(%.2g,%1d) = %.3f',sig/200,df2,t2))
else
   set(ud.CritVal2,'String','')
end   

NextPress= B(:,end);

p= size(ud.Model,1);
inmodel= Terms(ud.Model);
for i= 1:p
   params = ud.TermsOrder(i);
   % update table entries
   % Update errorbars
   set(ud.Hand.Point(i),'XData',beta(params));
   set(ud.Hand.Bar(i),'XData',Bint(params,:));
   if inmodel(params)
      % Terms in model
      set(ud.Hand.Point(i),'Color','k');
      set(ud.Hand.Bar(i),'Color','k');
   else
      % Terms out of model
      set(ud.Hand.Point(i),'Color','r');
      set(ud.Hand.Bar(i),'Color','r');
   end
end

inmodel= inmodel(ud.TermsOrder);
t= zeros(size(beta));
if ~all(B(:,2)==0)
   t(B(:,2)~=0)=beta(B(:,2)~=0)./B((B(:,2)~=0),2);
else
   t= zeros(size(beta));
end
Nums= [beta B(:,2) t NextPress];

% Find Minimum Press for next step
[MinPress,MinInd]=nanmin(NextPress(ud.TermsOrder));
ud.Hand.Table(:,end).backgroundcolor='w';
if MinPress < PRESS
   ud.Hand.Table(0,end).color='y'; 
   ud.Hand.Table(MinInd,end).backgroundcolor='y';
   % Highlight minimum press yellow
else
   ud.Hand.Table(0,end).color='k';
end

Nums(getstatus(ud.Model)==2,2:4)=NaN;
ud.Hand.Table(:,2:end)= Nums(ud.TermsOrder,:);

ud.Hand.Table(inmodel,0:end).ForeGroundColor  = 'k';
ud.Hand.Table(~inmodel,0:end).ForeGroundColor = 'r';

% X Axes Limits for ErrorBar Plot
% Don't include constant coeff in this calculation
set(get(ud.Hand.Bar(1),'Parent'),...
   'XLimMode','auto');

% Colour Insignicant intervals and errorbars purple
insig = Bint(:,1)<0 & Bint(:,2)>0;
insig = insig(ud.TermsOrder);

ud.Hand.Table(insig,end-1).foregroundcolor= 'b';
ud.Hand.Table(~insig,end-1).foregroundcolor= 'k';

set(ud.Hand.Bar(insig),'Color','b')
% set(ud.Hand.Bar(~insig),'color','k')

ud.Hand.Table.redraw;



gui_diagstats(ud.Model,'display',ud.Stats);



%------------------------------------------------------------------------
% SUBFUNCTION i_Radio
%------------------------------------------------------------------------
function i_Radio(~)

ud= get(gcbf,'UserData');

tbl= ud.Hand.Table;
rud= get(gcbo,'UserData');
if strcmp(tbl.vslider.visible,'on')
   StepTerm=rud.row+tbl.vslider.value-1;
else
   StepTerm=rud.row;
end   


TermStatus= get(gcbo,'Value');
OldStatus= getstatus(ud.Model);
if TermStatus~=OldStatus(ud.TermsOrder(StepTerm))
   
   i_DisplayStatus(ud,TermStatus,StepTerm)
   
   StepTerm= ud.TermsOrder(StepTerm);
   ud.Model=setstatus(ud.Model,StepTerm,TermStatus);
   % Do step
   [ud.Model,OK,NewPRESS,B]= stepwise(ud.Model,~Terms(ud.Model));
   if ~OK;
      % Step couldn't be taken
      errordlg('There is insufficient data to add this term to the model',...
         'Stepwise','modal'); 
      return
   end
   % Update display
   i_DisplayResults(ud,NewPRESS,B)
   i_UpdateHistory(NewPRESS,ud.Model,gcbf,ud.Hand.HistAxes);
   
   set(gcbf,'UserData',ud);
   
   % update browser view and other windows;
   ud.p_mdev.setmodel(ud.Model,OK);
   doUpdate(ud)
   figure(gcbf);
   
end 

% i_DisplayStatus
function i_DisplayStatus(ud,TermStatus,StepTerm)

switch TermStatus
case 1 
   % Term always incuded in Model
   
   % Display Confidence Intervals
   set(ud.Hand.Bar(StepTerm),'Visible','on')
   set(ud.Hand.Point(StepTerm),'Visible','on')
   if (ismember(1,StepTerm) && isconstant(ud.Model))
      % StepTerm= setdiff(StepTerm,1);
      set(ud.Hand.Bar(1),'Visible','off')
      set(ud.Hand.Point(1),'Visible','off')
   end
   
   ud.Hand.Table(StepTerm,3:end-1).Visible= 'on';
   % Hide Next PRESS text 
   % Disable ButtonDownFcn
   ud.Hand.Table(StepTerm,[0 end]).HitTest= 'off';
case 2
   % Term never incuded in Model
   
   % Hide Confidence Intervals and Next PRESS
   set(ud.Hand.Bar(StepTerm),'Visible','off')
   set(ud.Hand.Point(StepTerm),'Visible','off')
   
   % Disable ButtonDownFcn
   ud.Hand.Table(StepTerm,[0 end]).HitTest= 'off';
case 3
   % Term can be stepped in and out
   
   % Show Confidence Intervals and Next PRESS
   set(ud.Hand.Bar(StepTerm),'Visible','on')
   set(ud.Hand.Point(StepTerm),'Visible','on')
   if (ismember(1,StepTerm) && isconstant(ud.Model))
      % StepTerm= setdiff(StepTerm,1);
      set(ud.Hand.Bar(1),'Visible','off')
      set(ud.Hand.Point(1),'Visible','off')
   end
   
   % Enable ButtonDownFcn
   ud.Hand.Table(StepTerm,[0 end]).HitTest= 'on';
end


%------------------------------------------------------------------------
% SUBFUNCTION i_VSilder
%------------------------------------------------------------------------
function i_VSlider

ud= get(gcbf,'UserData');
OldYlim= get(ud.Hand.CIAxes,'YLim');

Top=get(ud.Hand.Table,'vslider.value');
set(ud.Hand.CIAxes,'YLim',Top-0.5+[0 diff(OldYlim)])

%------------------------------------------------------------------------
% SUBFUNCTION i_Step
%------------------------------------------------------------------------
function i_Step(~)
% Toggle single term (based on click in table or errorbar)
hFig=gcbf;
ud = get(hFig,'UserData');

tbl= ud.Hand.Table;
rud= get(gcbo,'UserData');
if ~isempty(rud)
   % click on table
   if strcmp(rud.type,'fixed')
      StepTerm= rud.row-tbl.rows.fixed;
   else
      % convert to index
      StepTerm=scrollindex(tbl,rud.row,rud.col);
   end
else
   % click on CI plot
   StepTerm= get(gcbo,'YData');
   StepTerm= StepTerm(1);
end
% Do step
StepTerm= ud.TermsOrder(StepTerm);
[ud.Model,OK,NewPRESS,B]= stepwise(ud.Model,StepTerm);
if ~OK;
   % Step couldn't be taken
   errordlg('There is insufficient data to add this term to the model',...
      'Stepwise','modal'); 
   return
end
set(hFig,'Pointer','watch');
% Update display
i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,ud.Model,hFig,ud.Hand.HistAxes);

% update browser view and other windows;
ud.p_mdev.setmodel(ud.Model,OK);
doUpdate(ud)
figure(hFig);
set(hFig,'Pointer','arrow');

%------------------------------------------------------------------------
% SUBFUNCTION i_MinPress
%------------------------------------------------------------------------
function i_MinPress(hFig)
% Take all steps to mininise PRESS

if ~nargin
   hFig=gcbf;
end

set(hFig,'Pointer','watch');
ud = get(hFig,'UserData');

om= minpress(ud.Model);
set(om,'isInitialised',true);
set(om,'guidisp',true)
[ud.Model,~,OK,NewPRESS,B]= run(om,ud.Model,ud);

% Update Coeff Table and ErrorBar Plots
i_DisplayResults(ud,NewPRESS,B)

% update modeldev's model
ud.p_mdev.setmodel(ud.Model,OK);
% update browser view and other windows;
doUpdate(ud)
figure(hFig);
set(hFig,'Pointer','arrow');


%------------------------------------------------------------------------
% SUBFUNCTION i_ChangeCrit
%------------------------------------------------------------------------
function i_ChangeCrit
% Change significance level for CI's

% Check entry is a valid %
if xregCheckIsNum('range',[0.1,10]);
   
   ud = get(gcbf,'UserData');
   
   % Calculate new critical values
   alpha   = get(gcbo,'UserData')/100;
   sigprob = 1 - alpha/2;
   % Set up critical values so df(SSR)+1 gives index to crit values
   df      = 1:ud.Nobs;  %:-1:ud.Nobs-size(ud.Model,1);
   ud.crit = i_Calctinv(sigprob,df);
   % recalculate all stats
   [~,OK,NewPRESS,B]= stepwise(ud.Model);
   % update displays
   i_DisplayResults(ud,NewPRESS,B)
   % Don't update history because model hasn't changed
   
   % update browser view and other windows;
   ud.p_mdev.setmodel(ud.Model,OK);
   doUpdate(ud)
   figure(gcbf);
end

%------------------------------------------------------------------------
% SUBFUNCTION i_RemoveInsig
%------------------------------------------------------------------------
function i_RemoveInsig(hFig)

if ~nargin
   hFig=gcbf;
end

ud = get(hFig,'UserData');

om= backwardselect(ud.Model);
set(om,'isInitialised',true);
set(om,'guidisp',true)
% turn off include all option
set(om,'includeall',false)
% run optimMgr
[ud.Model,~,OK,NewPRESS,B]= run(om,ud.Model,ud);

% Update Coeff Table and ErrorBar Plots
i_DisplayResults(ud,NewPRESS,B)
set(gcbf,'UserData',ud);



% Update displays
i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,ud.Model,hFig,ud.Hand.HistAxes);

% update modeldev's model
ud.p_mdev.setmodel(ud.Model,OK);
% update browser view and other windows;
doUpdate(ud)
figure(hFig);

%------------------------------------------------------------------------
% SUBFUNCTION i_AddSig
%------------------------------------------------------------------------
function i_AddSig(hFig)

if ~nargin
   hFig=gcbf;
end

ud = get(hFig,'UserData');

om= forwardselect(ud.Model);
set(om,'isInitialised',true);
set(om,'guidisplay',true)
% turn off include all option
set(om,'removeall',false)
% run optimMgr
[ud.Model,~,OK,NewPRESS,B]= run(om,ud.Model,ud);


% Update displays
i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,ud.Model,hFig,ud.Hand.HistAxes);

% update browser view and other windows;
% update modeldev's model
ud.p_mdev.setmodel(ud.Model,OK);
% update browser view and other windows;
doUpdate(ud)
figure(hFig);

%------------------------------------------------------------------------
% SUBFUNCTION i_IncludeAll
%------------------------------------------------------------------------
function i_IncludeAll(hFig)
% Include all terms in model

if ~nargin
   hFig=gcbf;
end

ud = get(hFig,'UserData');
% No Terms left out of model
OutModel = false(size(ud.Model));
% calculate new model
[ud.Model,OK,NewPRESS,B]= stepwise(ud.Model,OutModel);
if ~OK;
   % check that it is possible to include all terms in model
   errordlg('There is insufficient data to include all terms in this model',...
      'Stepwise','modal'); 
   return
end
% update displays
i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,ud.Model,hFig,ud.Hand.HistAxes);

% update browser view and other windows;
ud.p_mdev.setmodel(ud.Model,OK);
doUpdate(ud)
figure(hFig);


%------------------------------------------------------------------------
% SUBFUNCTION i_RemoveAll
%------------------------------------------------------------------------
function i_RemoveAll(hFig)
% Remove all terms for model (e.g. for Forward Selection)

if ~nargin
   hFig=gcbf;
end

ud = get(hFig,'UserData');
% All Terms left out of model
OutModel = true(size(ud.Model));
% calculate new model
[ud.Model,OK,NewPRESS,B]= stepwise(ud.Model,OutModel);
% update displays
i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,ud.Model,hFig,ud.Hand.HistAxes);
set(gcbf,'UserData',ud);

% update browser view and other windows;
ud.p_mdev.setmodel(ud.Model,OK);
doUpdate(ud)
figure(hFig);

%------------------------------------------------------------------------
% SUBFUNCTION i_History
%------------------------------------------------------------------------
function i_History(h,~,flag)
% Return to previous model (from History plot click)

fig = ancestor(h,'figure');
if isgraphics(h,'uicontrol');
   if ~strcmp(get(fig,'SelectionType'),'open')
      return
   end
   flag= get(h,'Value');
end
ud= get(fig,'UserData');
% histud stored in HistAxes UserData
histud= get(ud.Hand.HistAxes,'UserData');
in = histud.instore;
Terms = in(:,flag);
% Recalcuate old model
[ud.Model,OK,NewPRESS,B]= stepwise(ud.Model,Terms);
% Update Displays
i_DisplayResults(ud,NewPRESS,B)
i_UpdateHistory(NewPRESS,ud.Model,fig,ud.Hand.HistAxes);
set(fig,'UserData',ud);

% update browser view and other windows;
ud.p_mdev.setmodel(ud.Model,OK);
doUpdate(ud)
figure(fig);



%------------------------------------------------------------------------
% SUBFUNCTION i_UpdateHistory
%------------------------------------------------------------------------
function i_UpdateHistory(NewPRESS,Model,hFig,HistAxes)
% Local function for adding new press error bar to History Plot.

set(hFig,'CurrentAxes',HistAxes)
histud = get(HistAxes,'UserData');

tmp = ~Terms(Model);

if ~isfield(histud,'pressdothndl')   % No History
   histud.pressdothndl(1)=-1;
   histud.instore = tmp(:);
   num_mod = 1;
else  
   % Add New Model to history store
   in = histud.instore;
   in = [in tmp(:)];
   histud.instore = in;
   num_mod = length(histud.pressdothndl)+1;   
end
% plot CI bar

set(HistAxes,'XLim',[max(0.5,num_mod-19.5),num_mod+0.5],'XTick',(1:num_mod) );
% plot PRESS point
histud.pressdothndl(num_mod) = plot(num_mod,NewPRESS,'.k','Parent',HistAxes);

% Set ButtonDwn callbacks
set(histud.pressdothndl(num_mod),'MarkerSize',20,...
    'ButtonDownFcn',{@i_History,num_mod});

% Save history UserData
set(HistAxes,'UserData',histud);

% show summary statistics [nObs,NumParams,Box-Cox,PRESS RMSE,RMSE]
s=FitSummary(Model);
ud= get(hFig,'UserData');
str= [get(ud.Hand.hList,'String') 
   sprintf('%5d %6d %8.2g %10.4g %10.4g',s(1:5))];
set(ud.Hand.hList,'String',str,...
   'Value',size(str,1),...
   'ListboxTop',max(1,size(str,1)-8));

%------------------------------------------------------------------------
% SUBFUNCTION i_Close
%------------------------------------------------------------------------
function i_Close


hFig= findobj(get(0,'Children'),'flat','Tag','stepwisefig','Visible','on');

if ~isempty(hFig);
    figure(hFig(1));
    ud= get(hFig(1),'UserData');
    confirm=questdlg('Do you want to update Regression Results?',...
        'Confirm Stepwise Exit',...
        'Yes',...
        'No',...
        'Cancel',...
        'Yes');
    if isempty(confirm)
        confirm = 'Cancel';
    end
    if ~strcmp(confirm,'Cancel')
        if strcmp(confirm,'No') && size(get(ud.Hand.hList,'String'),1)>1
            % save old model - don't do this if there is only one entry in
            % history
            ud.p_mdev.setmodel(ud.OrigModel,1);
            doUpdate(ud)
        end
        % close DOE evaluation figure
        hDOE= findobj(get(0,'Children'),'flat','Tag','DOEtool','Visible','on');
        close(hDOE);
        set(hFig(1),'Visible','off');
        % Bring main Model Browser figure to foreground
        if isgraphics(ud.ParentFig,'figure')
            figure(ud.ParentFig)
        end
    end
end

 
%------------------------------------------------------------------------
% SUBFUNCTION i_Calctinv
%------------------------------------------------------------------------
function crit= i_Calctinv(sigprob,df)

df= df(:);
crit= zeros(size(df));
if max(df)>100
   crit(df<100)=  tinv(sigprob,df(df<100));
   crit(df>=100)=  norminv(sigprob);
else
   crit=  tinv(sigprob,df);
end

function refreshFigure(p_mdev,Model,ud,hFig)
Yname= p_mdev.name;
Constant = IncludeConst(Model);
[Model,~,NewPRESS,B]= stepwise(Model);
% (3,2) element is the df for SST 
Xdata= p_mdev.getdata('X');
Nobs= size(Xdata,1);

df   = 1:max(Nobs,size(Model,1)); 
alpha= get(ud.CritVal,'UserData')/100;
sigprob= 1-alpha/2;
ud.crit=  i_Calctinv(sigprob,df);
ud.Model      = Model;
ud.OrigModel  = Model;
ud.Constant   = Constant;
ud.p_mdev     = p_mdev;
ud.DoingUpdate = false;

Status= getstatus(Model); %#ok<*FOBS>
ud.Hand.Table(:,0).string= labels(Model);
ud.Hand.Table(:,1)=Status(ud.TermsOrder);
for i=1:3
   s= find(Status(ud.TermsOrder)==i);
   i_DisplayStatus(ud,i,s)
end

% Display Initial Results 
i_DisplayResults(ud,NewPRESS,B)


delete(get(ud.Hand.HistAxes,'Children'));
set(ud.Hand.hList,'String','');

histud= get(ud.Hand.HistAxes,'UserData');
histud= rmfield(histud,'pressdothndl');
set(ud.Hand.HistAxes,'UserData',histud,'XLim',[0 10],'YLimMode','auto');
i_UpdateHistory(NewPRESS,Model,hFig,ud.Hand.HistAxes);

set(hFig,'UserData',ud,...
   'Name',['Stepwise Regression for ',Yname]);

function [step_axes,bhandles,phandle] = createCIAxes(pnl,p,Model)
step_axes= axes('Parent',pnl,'NextPlot','add',...
   'Tag','stepaxes','Box','on',...
   'YDir','reverse',...
   'YTickLabel','','YTick',[],...
   'Units','pixels',...
   'FontSize',8);

title(step_axes,'Coefficients with Errorbars',...
   'FontSize',9)
% Make Lines and handles
% Vertical line at zero
plot([0 0],[0.5,p+0.5],'k-', 'Parent', step_axes);
bhandles = gobjects(p,1);
phandle = bhandles;
for k = 1:p
   % Interval Estimate
   bhandles(k,1)=line('Parent',step_axes,...
      'XData',[0 0]','YData',[k k],...
      'ButtonDownFcn',[mfilename,'(''click'',',int2str(k),')'],'LineWidth',2);
   % Point Estimate
   phandle(k,1)= line('Parent',step_axes,...
      'XData',0,'YData',k,...
      'Marker','.','MarkerSize',20,...
      'ButtonDownFcn',[mfilename,'(''click'',',int2str(k),')']);
end
if isconstant(Model)
   % Don't display errorbar for constant term as it is usually too large.
   set(phandle(1),'Visible','off');
   set(bhandles(1),'Visible','off');
end

function [CallBack,BottomLyt] = createButtons(table_fig)
% Stepwise Buttons (at bottom of Figure)
ToolTipString = {   'Minimize PRESS',...
   'Include all terms in model',...
   'Remove all terms from model',...
   'Forward addition of significant terms to model',...
   'Backwards removal of insignificant terms from model'};
String= {'Min. PRESS',...
      'Include All',...
      'Remove All',...
      'Forward',...
      'Backwards'};

CallBack= {[mfilename,'(''Auto'')'],...
      [mfilename,'(''IncludeAll'')'],...
      [mfilename,'(''RemoveAll'')'],...
      [mfilename,'(''AddSig'')'],...
      [mfilename,'(''Remove'')']};

  hButtons = cell(size(String));
for i=1:length(String)
   hButtons{i} = uicontrol('Parent',table_fig,...
      'Style','Pushbutton','Units','Pixels',...
      'String',String{i},...
		'BusyAction','cancel',...
      'TooltipString',ToolTipString{i},...
      'Callback',CallBack{i});
end
BottomLyt = xreggridlayout(table_fig,...
    'dimension',[1 length(String)+1],...
    'colsizes',[repmat(100,1,length(String)) -1],...
    'gapx',20,...
    'elements',hButtons);

function createMenus(table_fig,CallBack)
MainMenu= {'&Figure','&Regression'};
mmh= xregmenutool('create',table_fig,'Label',MainMenu);

% Figure Menu
hf=xregmenutool('create',mmh(1),'Label',{'&Close'},'Callback',{[mfilename,'(''Close'')']});
set(hf,'Accelerator','W');

Label= {'Minimize &PRESS',...
      '&Include All',...
      '&Remove All',...
      '&Forward',...
      '&Backwards'};

xregmenutool('create',mmh(2),'Label',Label,'CallBack',CallBack);

xregwinlist(table_fig); % initialize Window Menu

%HELP MENU
mv_helpmenu(table_fig,{'&Stepwise Help','xreg_stepwise'});

function [hLabels,hList] = createHistoryList(p_mdev,table_fig)
str=p_mdev.colhead;
% truncate these strings so cols line up okay
maxLength = [3 5 7 10 10];
numHeaders = min(length(str),5);
for i = 1:numHeaders
   thisLength = min(length(str{i}),maxLength(i));
   str{i} = str{i}(1:thisLength);
end

hLabels = uicontrol('Parent',table_fig,...
    'Units','pixels',...
    'Style','text',...
    'String',sprintf('%5s %6s %8s %10s %10s',str{:}),...
    'FontSize',9,...
    'FontName','Courier New',...
    'HorizontalAlignment','left',...
    'BackgroundColor',get(table_fig,'Color'));
hList=uicontrol('Parent',table_fig,...
   'Units','pixels',...
   'Style','listbox',...
   'String','',...
	'FontSize',9,...
   'FontName','Courier New',...
   'BackgroundColor','w',...
   'Callback',@i_History);

function HistPanel = createHistoryAxes(table_fig,Nobs,p)

HistPanel = mbcgui.widget.AxesPanel('Parent',table_fig,...
    'Border',[50 20 0 20]);
HistAxes = HistPanel.AxesHandle;
set(HistAxes,...
   'Units','pixels',...
   'Tag','HistoryAxes',...
   'Box','on',...
   'NextPlot','add',...
   'FontSize',8);
% Critical Values for PRESS CI's
trm  = Nobs:-1:Nobs-p-1;
trml = length(trm);
low  = 0.025;
hi   = 0.975;
histud.chi2crit = chi2inv([low(ones(trml,1),1) hi(ones(trml,1),1)],[trm' trm']); 
set(HistAxes,'UserData',histud);
set(get(HistAxes,'XLabel'),'String','Model Number','FontSize',9);
set(get(HistAxes,'Title'),'String','Stepwise PRESS History','FontSize',9);					

function [ud,CIlyt] = createCIControls(alpha,table_fig,ud)
% Confidence Interval label and edit box 
hAlpha = uicontrol('Parent',table_fig,...
   'Style','text','Units','Pixels',...
   'FontName','Symbol',...
   'String','a (%)', ...
   'HorizontalAlignment','left');
ud.CritVal= uicontrol('Parent',table_fig,...
   'Style','edit','Units','Pixels',...
   'String',alpha*100,'UserData',alpha*100, ...
   'Callback',[mfilename,'(''crit'')'],...
   'BackgroundColor','w',...
   'Tag', 'crit');
ud.CritVal1= uicontrol('Parent',table_fig,...
   'Style','text','Units','Pixels',...
   'String','a (%)', ...
   'BackgroundColor','w',...
   'ForegroundColor','k');
ud.CritVal2= uicontrol('Parent',table_fig,...
   'Style','text','Units','Pixels',...
   'String','a (%)', ...
   'BackgroundColor','w',...
   'ForegroundColor','r');

CIlyt = xreggridlayout(table_fig,....
    'dimension',[1 4],...
    'colsizes',[39 69 -1 -1],...
    'CorrectAlg','on',...
    'elements',{hAlpha,ud.CritVal,ud.CritVal1,ud.CritVal2});


function doUpdate(ud)

if ~ud.DoingUpdate && ~isempty(ud.UpdateFcn)
    ud.DoingUpdate = true;
    set(ud.Hand.Figure,'UserData',ud);
    ud.UpdateFcn();
end