function regstats(responses,data,model)
%REGSTATS Regression diagnostics for linear models.
%   REGSTATS(RESPONSES,DATA,MODEL) fits a multiple regression of the
%   measurements in the vector, RESPONSES on the values in the matrix,
%   DATA. The function creates a UI that displays a group of checkboxes
%   that save diagnostic statistics to the base workspace using specified
%   variable names. MODEL, controls the order of the regression
%   model. By default, REGSTATS uses a linear additive model
%   with a constant term. MODEL can be following strings:
%   interaction - includes constant, linear, and cross product terms.
%   quadratic - interactions plus squared terms.
%   purequadratic - includes constant, linear and squared terms.

%   Reference Goodall, C. R. (1993). Computation using the QR decomposition. 
%   Handbook in Statistics, Volume 9.  Statistical Computing
%   (C. R. Rao, ed.).   Amsterdam, NL: Elsevier/North-Holland.

%   B.A. Jones 1-17-95
%   Copyright (c) 1993-96 by The MathWorks, Inc.
%   $Revision: 2.2 $  $Date: 1996/02/13 23:35:29 $

if ~isstr(responses) 
    action = 'start';
else
    action = responses;
end

%On recursive calls get all necessary handles and data.
if ~strcmp(action,'start')
  tmp = get(gcf,'UserData');
  [m,n] = size(tmp);
  y = tmp(:,1);
  X = tmp(:,2:n);
end

%Initialize GUI
if strcmp(action,'start')
   if nargin < 3
      model = 'linear';
   end
   X = x2fx(data,model);
   diagfig = figure('Units','Normalized',...
           'Position',[0.1 0.5 0.5 0.5],'Color',[.5 .5 .5],...
         'Userdata',[responses X]);

   textlables = str2mat('Q from QR Decomposition','R from QR Decomposition','Coefficients','Coefficient Covariance','Fitted Values');
   textlables = str2mat(textlables,'Residuals','Mean Square Error');
   textlables = str2mat(textlables,'Leverage','Hat Matrix','Delete-1 Variance');
   textlables = str2mat(textlables,'Delete-1 Coefficients','Standardized Residuals');
   textlables = str2mat(textlables,'Studentized Residuals','Change in Beta',...
                    'Change in Fitted Value','Scaled change in Fit');
   textlables = str2mat(textlables,'Change in Covariance','Cook''s Distance');

   varnames = str2mat('Q','R','beta','covb','yhat');
   varnames = str2mat(varnames,'r','mse');
   varnames = str2mat(varnames,'leverage','hatmat','s2_i');
   varnames = str2mat(varnames,'beta_i','standres');
   varnames = str2mat(varnames,'studres','dfbeta','dffit','dffits');
   varnames = str2mat(varnames,'covratio','cookd');

   uicontrol(diagfig,'Style','text',...
          'Position',[0.02 0.92 0.4 0.04],...
          'Units','normalized','BackgroundColor',[.5 .5 .5],...
          'String','Regression Diagnostics','ForegroundColor','w');

   uicontrol(diagfig,'Style','Pushbutton',...
          'Position',[0.5 0.92 0.3 0.06],...
          'Units','normalized','BackgroundColor',[.5 .5 .5],...
          'String','Calculate Now','ForegroundColor','w',...
        'Callback',['regstats(''calculate'')']);

   chkboxes = zeros(18,1);
   for k = 1:18
     boxcol = rem(k-1,9)+1;
    boxrow = floor(k/9-eps);
     chkboxes(k) = uicontrol(diagfig,'Style','checkbox',...
         'Position',[0.02+0.45*boxrow 0.9-0.1*boxcol 0.4 0.07],...         
         'Units','normalized','BackgroundColor','w',...
       'String',textlables(k,:),'Tag',int2str(k),...
       'UserData',varnames(k,:),...
         'ForegroundColor','k');

    end

close_button = uicontrol('Style','Pushbutton','Units','normalized',...
               'Position',[0.90 0 0.07 0.07],'Callback','close','String','Close');

help_button = uicontrol('Style','Pushbutton','Units','normalized',...
               'Position',[0.90 0.10 0.07 0.07],'Callback','hthelp(''regdoc.html'')','String','Help');

elseif strcmp(action,'calculate')
  [Q,R]=qr(X,0);
  beta = R\(Q'*y);
  yhat = X*beta;
  residuals = y - yhat;
  nobs = length(y);
  p = min(size(R));
  mse = sum(residuals.*residuals)./(nobs-p);
  E = X/R;
  h = sum((E.*E)')';
  s_sqr_i = ((nobs-p)*mse - residuals.*residuals./(1-h))./(nobs-p-1);
  e_i = residuals./sqrt(s_sqr_i.*(1-h));
  ri = R\eye(p);
  xtxi = ri*ri';
  
  varhandles = zeros(18,1);
  idx = (1:18)';
  varnames = zeros(18,8);
  for k = 18:-1:1
    varhandles(k) = findobj(gcf,'Tag',int2str(k));
   if get(varhandles(k),'Value') == 0, idx(k) = [];end
   varnames(k,:) = get(varhandles(k),'UserData');
  end
  
  for k=1:length(idx)
     if k == 1
       entrystr = deblank(varnames(idx(1),:));
    else
        entrystr = [entrystr,', ',deblank(varnames(idx(k),:))];
    end
  end
  
  if (any(idx == 1))
    % Q from the QR decomposition of the X matrix.
     matqueue('put',Q);
  end
  if (any(idx == 2))
    % R from the QR decomposition of the X matrix.
     matqueue('put',R);
  end
  if (any(idx == 3))
    % Coefficients.
     matqueue('put',beta);
  end
  if (any(idx == 4))
    % Covariance of the parameters.
     covb = xtxi*mse;
     matqueue('put',covb);
  end
  if (any(idx == 5))
    % Fitted values.
     matqueue('put',yhat);
  end
  if (any(idx == 6))
     % Residuals.
    matqueue('put',residuals);
  end
  if (any(idx == 7))
    % Mean squared error.
     matqueue('put',mse);
  end
  if (any(idx == 8))
    % Leverage.
     matqueue('put',h);
  end
  if (any(idx == 9))
    % Hat Matrix.
     matqueue('put',Q*Q');
  end
  if (any(idx == 10))
    % Delete 1 variance. S_I
     matqueue('put',s_sqr_i);
  end
  if (any(idx == 11)) | (any(idx == 14))
    % Delete 1 coefficients. BETA_I
   stde = residuals./(1-h);
   stde = stde(:,ones(p,1));
   b_i = beta(:,ones(m,1)) - ri*(Q.*stde)';
    
     if (any(idx == 11)),matqueue('put',b_i);end
  end
  if (any(idx == 12))
    % Standardized residuals.
     matqueue('put',residuals./(sqrt(mse*(1-h))));
  end
  if (any(idx == 13))
     % Studentized residuals. 
     matqueue('put',e_i);
  end
  if (any(idx == 14)) 
   % Change in beta. DFBETAS
     b = beta(:,ones(nobs,1));
    s = sqrt(s_sqr_i(:,ones(p,1))');
    rtri = sqrt(diag(xtxi));
    rtri = rtri(:,ones(nobs,1));
    dfbeta = (b - b_i)./(s.*rtri);
     matqueue('put',dfbeta);
  end
  if (any(idx == 15))
   % Change in fitted values. DFFIT
     matqueue('put',h.*residuals./(1-h));
  end
  if (any(idx == 16))
   % Scaled change in fitted values. DFFITS
     matqueue('put',sqrt(h./(1-h)).*e_i);
  end
  if (any(idx == 17))
   %  Change in covariance. COVRATIO
    covr = (((nobs-p-1+e_i.*e_i)./(nobs-p)).^p)./(1-h);
     matqueue('put',covr);
  end
  if (any(idx == 18))
   %  Cook's Distance.
    d = residuals.*residuals.*(h./(1-h))./p;
     matqueue('put',d);
  end
  
  promptstr = 'Enter variable names for regression diagnostics or use defaults.';
  matqdlg('buffer2ws','PromptString',promptstr,'EntryString',entrystr);
end
