function rstool(x,y,model,alpha,xname,yname)
%RSTOOL Interactive fit and plot of a multidimiensional response surface (RSM).
%   RSTOOL(X,Y,MODEL,ALPHA) is a prediction plot that provides a 
%   multiple input polynomial fit to (X,y) data. It plots a 100(1 - ALPHA) 
%   percent global confidence interval for predictions as two red curves. 
%   The default model is linear. 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.
%   The default value for ALPHA is 0.05, which produces 95% confidence 
%   intervals.
%
%   RSTOOL(X,Y,MODEL,ALPHA,XNAME,YNAME) The optional inputs XNAME and 
%   YNAME contain strings for the X and Y variables respectively.
%
%   Drag the dotted white reference 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.
%   Use the pop-up menu labeled model to interactively change the model.
%   Use the pop-up menu labeled Export to move specified variables to
%   the base workspace.
   
%   B.A. Jones 1-30-94
%   Copyright (c) 1993-96 by The MathWorks, Inc.
%   $Revision: 2.2 $  $Date: 1996/02/13 23:36:42 $

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

%On recursive calls get all necessary handles and data.
if ~strcmp(action,'start')
   if nargin == 2,
      flag = y;
   end

   lin_fig = findobj(0,'Tag','linfig');
   if strcmp(action,'down')
       set(lin_fig,'WindowButtonMotionFcn','rstool(''motion'',1)');
    end

   k = gcf;
   idx = find(lin_fig == k);
   if isempty(idx)
      return
   end
   lin_fig = lin_fig(idx);      
   ud = get(lin_fig,'Userdata');
   
   crit          = ud(1);
   rmse          = ud(2);
   popup         = ud(3);
   
   Rinv          = get(ud(4),'Userdata');
   beta          = get(ud(5),'Userdata');
   model         = get(ud(6),'Userdata');
   x             = get(ud(7),'Userdata');
   y             = get(ud(8),'Userdata');
   xfit          = get(ud(9),'Userdata');
   residuals     = get(ud(10),'Userdata');
   x_field       = get(ud(11),'Userdata');
   lin_axes      = get(ud(12),'Userdata');
   xsettings     = get(ud(13),'Userdata');
   y_field1      = ud(14);
   y_field2      = ud(15);
   y_field3      = ud(16);
   modelpopup    = ud(17);
   alpha         = ud(18);
   
   [m,n]         = size(x);

    fitline        = zeros(3,n);
    reference_line = zeros(n,2);
   xrange         = zeros(n,2);
   yrange         = zeros(n,2);
   newx           = zeros(n,1);
   newy           = zeros(1,1);
    last_axes      = zeros(n,1);
     for k = 1:n      
      axes_ud             = get(lin_axes(k),'UserData');
       fitline(1:3,k)      = axes_ud(1:3)';
       reference_line(k,:) = axes_ud(4:5);
      last_axes(k)        = axes_ud(6);
   
        xrange(k,1:2) = get(lin_axes(k),'XLim');
        yrange(k,1:2) = get(lin_axes(k),'YLim');

        newx(k) = str2num(get(x_field(k),'String'));
        
     end
      newy = str2num(get(y_field1,'String'));  
end

if strcmp(action,'start')

if nargin < 4, 
    alpha = 0.05;
end
if isempty(alpha)
    alpha = 0.05;
end


if nargin < 3
   model = 'additive';
   mval  = 1;
   name  = 'Linear';
end
if isempty(model)
   model = 'additive';
   mval  = 1;
   name  = 'Linear';
end
if strcmp(model,'purequadratic') | strcmp(model,'p'),
   mval  = 2;
   name  = 'Pure Quadratic';
elseif strcmp(model,'interaction') | strcmp(model,'i'),
   mval  = 3;
   name  = 'Interactions';
elseif strcmp(model,'quadratic') | strcmp(model,'q'),
   mval  = 4;
   name  = 'Full Quadratic';
end

[m,n]  = size(x);

design = x2fx(x,model);

% Fit response surface model design
[Q R] = qr(design,0);
if rcond(R) < 1E-12
    s = ['Your data is insufficient to fit a ',name, ' model.'];
    error(s);
end

beta = R\(Q'*y);
Rinv = R\eye(size(R));

yhat = design*beta;
residuals = y - yhat;

p = length(beta);
df = max(size(y)) - p;

rmse = sqrt(sum(residuals.*residuals)./df);
crit = sqrt(p*finv(1 - alpha,p,df))*rmse;

% Set positions of graphic objects
maxx = max(x);
minx = min(x);
xrange = maxx - minx;
maxx = maxx + 0.025 .* xrange;
minx = minx - 0.025 .* xrange;
xrange = 1.05*xrange;

yfieldp = [.01 .45 .13 .04];

bcolor = [0.5 0.5 0.5];


x_field        = zeros(n,1);
lin_axes       = zeros(n,1);
fitline        = zeros(n,3);
reference_line = zeros(n,2);

xfit      = xrange(ones(41,1),:)./40;
xfit(1,:) = minx;
xfit      = cumsum(xfit);

avgx      = mean(x);

xsettings = avgx(ones(42,1),:);

lin_fig = figure('Units','Normalized','Interruptible','yes',...
                'Position',[0.05 0.45 0.90 0.5],'Color','k',...
             'Name',['Prediction Plot of ',name,' Model'],'Tag','linfig');
set(lin_fig,'WindowButtonMotionFcn','rstool(''motion'',0)');
set(lin_fig,'WindowButtonDownFcn','rstool(''down'')');
set(lin_fig,'WindowButtonUpFcn','rstool(''up'')','Interruptible','yes');

gray_axes = axes;
set(gray_axes,'XTick',[],'YTick',[],'Units','Normalized','Position',[0 0 1 1],...
  'Color',bcolor,'ButtonDownFcn','rstool(''stray_click'')');

yextremes = zeros(k,2);

for k = 1:n
   % Create an axis for each input (x) variable
 
    xfieldp = [.18 + (k-0.5)*.80/n - 0.5*min(.5/n,.18) .09 min(.5/n,.18) .07];
    xtextp = [.18 + (k-0.5)*.80/n - 0.5*min(.5/n,.18) .02 min(.5/n,.18) .05];
    axisp   = [.18 + (k-1)*.80/n .22 .80/n .68];

    lin_axes(k) = axes;
    set(lin_axes(k),'XLim',[minx(k) maxx(k)],'Box','on','NextPlot','add',...
        'DrawMode','fast','Position',axisp,'Color','k');

   if k>1
      set(lin_axes(k),'Yticklabels',[]);
   end

   % Calculate y values for fitted line plot.
   ith_x      = xsettings;
   ith_x(1:41,k) = xfit(:,k);
   
    ith_x(42,k)  = avgx(k);
    
   xpred = x2fx(ith_x,model);

   yfit       = xpred(1:41,:)*beta;
   newy       = xpred(42,:)*beta;

   xi         = xfit(:,k);
   
   % Calculate y values for confidence interval lines.
   E = xpred(1:41,:)*Rinv;
   dy = (sqrt(sum((E.*E)'))*crit)';

   % Plot prediction line with confidence intervals
   set(0,'CurrentFigure',lin_fig);
   set(lin_fig,'CurrentAxes',lin_axes(k));
   fitline(1:3,k) = plot(xi,yfit,'g-',xi,yfit-dy,'r--',xi,yfit+dy,'r--');
   xl = get(lin_axes(k),'Xlim');
   xr = diff(xl);
   xt = get(lin_axes(k),'XTick');
   lowtick = xl(1) + .1*xr;
   hitick  = xl(2) - .1*xr;
   xt = xt(find(xt>lowtick & xt<hitick));
   set(lin_axes(k),'Xtick',xt);
   % Calculate data for vertical reference lines
   yextremes(k,:) = get(gca,'YLim');

    xvert = ones(size(yextremes)) * avgx(k);

   E = xpred(42,:)*Rinv;
   deltay = sqrt(E*E')*crit;

    x_field(k)  = uicontrol(lin_fig,'Style','edit','Position',xfieldp,...
         'Units','normalized','String',num2str(ith_x(42,k)),...
         'BackgroundColor','white','CallBack',['rstool(''edittext'',',int2str(k),')']);
    if nargin >= 5
      xstr = xname(k,:);
      if isempty(xname)
         xstr = ['X',int2str(k)];
      end  
   else
      xstr = ['X',int2str(k)];
   end
    uicontrol(lin_fig,'Style','text','Position',xtextp,...
        'Units','normalized','BackgroundColor',bcolor,...
        'ForegroundColor','w','String',xstr);
end  % End of the plotting loop over all the axes.
    
if nargin == 6
   ystr = yname;
else
   ystr = 'Predicted Y';
end
    
uicontrol(lin_fig,'Style','text','Position',yfieldp + [0 0.21 0 0],...
        'Units','normalized','BackgroundColor',bcolor,...
        'ForegroundColor','w','String',ystr);

ymin = min(yextremes(:,1));
ymax = max(yextremes(:,2));
   
%   Create Reference Lines
for k = 1:n
   set(lin_axes(k),'YLim',[ymin ymax]);
   xlimits = get(lin_axes(k),'XLim');
   %   Create Reference Lines
    xvert = ones(size(yextremes(k,:))) * avgx(k);
   set(lin_fig,'CurrentAxes',lin_axes(k));
   reference_line(k,1) = plot(xvert,[ymin ymax],'w--','Erasemode','xor');
   reference_line(k,2) = plot(xlimits,[newy newy],'w:','Erasemode','xor');
   set(reference_line(k,1),'ButtonDownFcn','rstool(''down'')');
   set(lin_axes(k),'UserData',[fitline(1:3,k)' reference_line(k,:) 0]);
end

y_field1 = uicontrol(lin_fig,'Style','text','Units','normalized',...
     'Position',yfieldp + [0 .14 0 0],'String',num2str(newy),...
     'ForegroundColor','white','BackgroundColor',bcolor);

y_field2 = uicontrol(lin_fig,'Style','text','Units','normalized',...
     'Position',yfieldp + [0 .07 -0.01 0],'String',' +/-',...
     'ForegroundColor','w','BackgroundColor',bcolor);

y_field3 = uicontrol(lin_fig,'Style','text','Units','normalized',...
     'Position',yfieldp,'String',num2str(deltay),...
     'ForegroundColor','w','BackgroundColor',bcolor);

popup        = uicontrol(lin_fig,'Style','Popup','String',...
              'Export|Parameters|RMSE|Residuals|All','Value',1,...
              'Units','normalized','Position',[0.01 0.15 0.13 .05],...
              'CallBack','rstool(''output'')');

modelpopup   = uicontrol(lin_fig,'Style','Popup','String',...
              'Linear|Pure Quadratic|Interactions|Full Quadratic','Value',mval,...
              'Units','normalized','Position',[0.01 0.08 0.13 0.05],...
              'CallBack','rstool(''changemodel'')','Userdata',mval);

close_button = uicontrol('Style','Pushbutton','Units','normalized',...
               'Position',[0.01 0.01 0.13 0.05],'Callback','close','String','Close');

Rinvstore=uicontrol('Style','text','Visible','off','UserData',Rinv);

betastore=uicontrol('Style','text','Visible','off','UserData',beta);

modelstore=uicontrol('Style','text','Visible','off','UserData',model);

xstore=uicontrol('Style','text','Visible','off','UserData',x);

ystore=uicontrol('Style','text','Visible','off','UserData',y);

xfieldstore=uicontrol('Style','text','Visible','off','UserData',x_field);

xfitstore=uicontrol('Style','text','Visible','off','UserData',xfit);

residualstore=uicontrol('Style','text','Visible','off','UserData',residuals);

lin_axesstore=uicontrol('Style','text','Visible','off','UserData',lin_axes);

xsettingstore=uicontrol('Style','text','Visible','off','UserData',xsettings);

ud = [crit rmse popup Rinvstore betastore modelstore xstore ystore...
      xfitstore residualstore xfieldstore lin_axesstore...
     xsettingstore y_field1 y_field2 y_field3 modelpopup alpha];

set(lin_fig,'UserData',ud);

% Finished with plot startup function.

elseif strcmp(action,'motion'),
    p = get(lin_fig,'CurrentPoint');
   k = floor(1+n*(p(1)-0.18)/.80);
   if k < 1 | k > n | p(2) > 0.90 | p(2) < 0.22
      return
   end
   maxx = xrange(k,2);
   minx = xrange(k,1);
    set(lin_fig,'CurrentAxes',lin_axes(k));
    if flag == 0,
      cursorstate = get(lin_fig,'Pointer');
        cp = get(lin_axes(k),'CurrentPoint');
        cx = cp(1,1);
        cy = cp(1,2);
        fuzz = 0.02 * (maxx - minx);
        online = cx > newx(k) - fuzz & cx < newx(k) + fuzz;
        if online & strcmp(cursorstate,'arrow'),
            cursorstate = 'crosshair';
        elseif ~online & strcmp(cursorstate,'crosshair'),
            cursorstate = 'arrow';
        end
        set(lin_fig,'Pointer',cursorstate);
      return
   elseif flag == 1,
       if last_axes(k) == 0
         return;
      end
        cp = get(lin_axes(k),'CurrentPoint');
        cx=cp(1,1);
        if cx > maxx
            cx = maxx;
        end
        if cx < minx
            cx = minx;
        end

       xrow  = xsettings(1,:);
       xrow(k) = cx;
      
      drow = x2fx(xrow,model);
      yrow = drow*beta;
       E = drow*Rinv;
       deltay = sqrt(E*E')*crit;

      xsettings(:,k) = cx(ones(42,1));
       set(ud(13),'Userdata',xsettings);            
       set(lin_fig,'Userdata',ud);       
        set(x_field(k),'String',num2str(cx));
        set(y_field1,'String',num2str(yrow));      
        set(y_field3,'String',num2str(deltay));      
        set(reference_line(k,1),'XData',cx*ones(2,1));
        set(reference_line(k,2),'YData',[yrow; yrow]);
       
   end  % End of code for dragging reference lines

elseif strcmp(action,'down'),
    p = get(lin_fig,'CurrentPoint');
   k = floor(1+n*(p(1)-0.18)/.80);
   if k < 1 | k > n | p(2) > 0.90 | p(2) < 0.22
      return
   end
   axud = get(lin_axes(k),'UserData');
   axud(6) = 1;
   set(lin_axes(k),'UserData',axud);
    set(lin_fig,'Pointer','crosshair');
       
   cp = get(lin_axes(k),'CurrentPoint');
    cx=cp(1,1);
    if cx > maxx
       cx = maxx;
    end
    if cx < minx
       cx = minx;
    end

   xrow  = xsettings(1,:);
   xrow(k) = cx;
      
   drow = x2fx(xrow,model);
   yrow = drow*beta;
   E = drow*Rinv;
   deltay = sqrt(E*E')*crit;
      

   xsettings(:,k) = cx(ones(42,1));
   set(ud(13),'Userdata',xsettings);            
   set(lin_fig,'Userdata',ud);       
    set(x_field(k),'String',num2str(cx));
    set(y_field1,'String',num2str(yrow));      
    set(y_field3,'String',num2str(deltay));      
    set(reference_line(k,1),'XData',cx*ones(2,1));
    set(reference_line(k,2),'YData',[yrow; yrow]);

elseif strcmp(action,'up'),
    p = get(lin_fig,'CurrentPoint');
   k = floor(1+n*(p(1)-0.18)/.80);
   lk = find(last_axes == 1);
   if isempty(lk)
      return
   end
   if k < lk
      set(x_field(lk),'String',num2str(xrange(lk,1)));
   elseif k > lk
      set(x_field(lk),'String',num2str(xrange(lk,2)));
   end

   cx    = str2num(get(x_field(lk),'String'));  

   xrow  = xsettings(1,:);
   xrow(lk) = cx;

      
   xsettings(:,lk) = cx(ones(42,1));

   set(reference_line(lk),'XData',cx*ones(2,1));
   
   ymax = zeros(n,1);
   ymin = zeros(n,1);

   for ix = 1:n       

   % Calculate y values for fitted line plot.
   ith_x      = xsettings;
   ith_x(1:41,ix) = xfit(:,ix);
   
    ith_x(42,lk)  = cx;
    
   xpred = x2fx(ith_x,model);
   yfit       = xpred(1:41,:)*beta;
   cy         = xpred(42,:)*beta;

   E  = xpred(1:41,:)*Rinv;
   dy = (sqrt(sum((E.*E)'))*crit)';

   E = xpred(42,:)*Rinv;
   dcy = sqrt(E*E')*crit;

            
     set(ud(13),'Userdata',xsettings);            
     set(lin_fig,'Userdata',ud);       
     set(fitline(1,ix),'Ydata',yfit);
     set(fitline(2,ix),'Ydata',yfit-dy);
     set(fitline(3,ix),'Ydata',yfit+dy);
     ymax(ix) = max(yfit+dy);
     ymin(ix) = min(yfit-dy);         
    end
   
   for ix = 1:n
      axud = get(lin_axes(ix),'Userdata');
      axud(6) = 0;
      set(lin_axes(ix),'Ylim',[min(ymin) max(ymax)],'UserData',axud);
      set(reference_line(ix,1),'Ydata',[min(ymin) max(ymax)]);
       set(reference_line(ix,2),'YData',[cy cy]);
   end

   set(y_field1,'String',num2str(cy));
   set(y_field3,'String',num2str(dcy));
    set(lin_fig,'WindowButtonMotionFcn','rstool(''motion'',0)');

elseif strcmp(action,'edittext'),
   cx    = str2num(get(x_field(flag),'String'));  

   if isempty(cx)
        set(x_field(flag),'String',num2str(xsettings(1,flag)));
       % Create Bad Settings Warning Dialog.
       warndlg('Please type only numbers in the editable text fields.');
      mval = get(modelpopup,'Userdata');
      set(modelpopup,'Value',mval);
       return
   end  
   
   xl = get(lin_axes(flag),'Xlim');
   if cx < xl(1) | cx > xl(2)
       % Create Bad Settings Warning Dialog.
       warndlg('This number is outside the range of the data for this variable. Resetting to previous data value.');
      mval = get(modelpopup,'Userdata');
      set(modelpopup,'Value',mval);
       set(x_field(flag),'String',num2str(xsettings(1,flag)));
       return
   end
   

   xrow  = xsettings(1,:);
   xrow(flag) = cx;

      
   xsettings(:,flag) = cx(ones(42,1));

   set(reference_line(flag,1),'XData',cx*ones(2,1));
   
   ymax = zeros(n,1);
   ymin = zeros(n,1);

   for ix = 1:n       

   % Calculate y values for fitted line plot.
   ith_x      = xsettings;
   ith_x(1:41,ix) = xfit(:,ix);
   
    ith_x(42,flag)  = cx;
    
   xpred = x2fx(ith_x,model);
   yfit       = xpred(1:41,:)*beta;
   cy         = xpred(42,:)*beta;

   E  = xpred(1:41,:)*Rinv;
   dy = (sqrt(sum((E.*E)'))*crit)';

   E = xpred(42,:)*Rinv;
   dcy = sqrt(E*E')*crit;

            
     set(ud(13),'Userdata',xsettings);            
     set(lin_fig,'Userdata',ud);       
     set(fitline(1,ix),'Ydata',yfit);
     set(fitline(2,ix),'Ydata',yfit-dy);
     set(fitline(3,ix),'Ydata',yfit+dy);
     ymax(ix) = max(yfit+dy);
     ymin(ix) = min(yfit-dy);         
    end
   
   for ix = 1:n
      set(lin_axes(ix),'Ylim',[min(ymin) max(ymax)]);
      set(reference_line(ix,1),'Ydata',[min(ymin) max(ymax)]);
       set(reference_line(ix,2),'YData',[cy cy]);
   end

   set(y_field1,'String',num2str(cy));
   set(y_field3,'String',num2str(dcy));

elseif strcmp(action,'output'),
    bmf = get(lin_fig,'WindowButtonMotionFcn');
    bdf = get(lin_fig,'WindowButtonDownFcn');
    set(lin_fig,'WindowButtonMotionFcn','');
    set(lin_fig,'WindowButtonDownFcn','');
   cases = get(popup,'Value');
   if cases == 2
      matqueue('put',beta);
      promptstr = 'Enter the variable name for the fitted parameters or use default:';
      matqdlg('buffer2ws','PromptString',promptstr,'EntryString','beta');
   elseif cases == 3
      matqueue('put',rmse);
      promptstr = 'Enter the variable name for the RMSE of the fit or use default:';
      matqdlg('buffer2ws','PromptString',promptstr,'EntryString','rmse');
   elseif cases == 4;
      matqueue('put',residuals);
      promptstr = 'Enter the variable name for the residuals or use default:';
      matqdlg('buffer2ws','PromptString',promptstr,'EntryString','residuals');
   elseif cases == 5;
      matqueue('put',beta);
      matqueue('put',rmse);
      matqueue('put',residuals);
      entrystr = 'beta,rmse,residuals';
      promptstr = 'Enter names for the regression statistics or use the defaults:';
      matqdlg('buffer2ws','PromptString',promptstr,'EntryString',entrystr);
   end
   set(popup,'Value',1);
    set(lin_fig,'WindowButtonMotionFcn',bmf);
    set(lin_fig,'WindowButtonDownFcn',bdf);

elseif strcmp(action,'changemodel'),
   cases = get(modelpopup,'Value');
   if cases == 1
      model = 'linear';
   elseif cases == 2
      model = 'purequadratic';
   elseif cases == 3
      model = 'interaction';
   elseif cases == 4
      model = 'quadratic';
   end
    
   design = x2fx(x,model);

    % Fit response surface model design
    [Q, R] = qr(design,0);
   if rcond(R'*R) < 1E-16
        % Create Model Warning Figure.
       s = ['Your data is insufficient to fit a ',model, ' model. Resetting to previous model.'];
        warndlg(s);
      mval = get(modelpopup,'Userdata');
      set(modelpopup,'Value',mval);

          if mval == 1
          set(lin_fig,'Name','Prediction Plot of Linear Model')
       elseif mval == 2
          set(lin_fig,'Name','Prediction Plot of Pure Quadratic Model')
       elseif mval == 3
          set(lin_fig,'Name','Prediction Plot of Interactions Model')
       elseif mval == 4
          set(lin_fig,'Name','Prediction Plot of Full Quadratic Model')
       end
        drawnow;
       return;
   end
    beta = R\(Q'*y);
    Rinv = R\eye(size(R));

    yhat = design*beta;
    residuals = y - yhat;

    p = length(beta);
    df = max(size(y)) - p;

    rmse = sqrt(sum(residuals.*residuals)./df);
    crit = sqrt(p*finv(1 - alpha,p,df))*rmse;

    ymax = zeros(n,1);
    ymin = zeros(n,1);
    
   for k = 1:n
         % Calculate y values for fitted line plot.
      ith_x      = xsettings;
      ith_x(1:41,k) = xfit(:,k);
   
       ith_x(42,k)  = xsettings(1,k);
      xpred      = x2fx(ith_x,model);

      yfit       = xpred(1:41,:)*beta;
      newy       = xpred(42,:)*beta;

      xi         = xfit(:,k);
   
      % Calculate y values for confidence interval lines.
      E = xpred(1:42,:)*Rinv;
      dy = (sqrt(sum((E.*E)'))*crit)';
      dcy = dy(42);
      dy = dy(1:41);

      % Plot prediction line with confidence intervals
      set(0,'CurrentFigure',lin_fig);
      set(lin_fig,'CurrentAxes',lin_axes(k));
      set(fitline(1,k),'Xdata',xi,'Ydata',yfit);
      set(fitline(2,k),'Xdata',xi,'Ydata',yfit-dy);
      set(fitline(3,k),'Xdata',xi,'Ydata',yfit+dy);
      ymax(k) = max(yfit+dy);
      ymin(k) = min(yfit-dy);         
    end
   
   for ix = 1:n
      set(lin_axes(ix),'Ylim',[min(ymin) max(ymax)]);
      set(reference_line(ix,1),'Ydata',[min(ymin) max(ymax)]);
       set(reference_line(ix,2),'YData',[newy; newy]);
   end
   
   set(y_field1,'String',num2str(newy));
   set(y_field3,'String',num2str(dcy));

   if cases == 1
      set(lin_fig,'Name','Prediction Plot of Linear Model')
   elseif cases == 2
      set(lin_fig,'Name','Prediction Plot of Pure Quadratic Model')
   elseif cases == 3
      set(lin_fig,'Name','Prediction Plot of Interactions Model')
   elseif cases == 4
      set(lin_fig,'Name','Prediction Plot of Full Quadratic Model')
   end
   set(modelpopup,'Userdata',cases);
   ud(1) = crit;
   ud(2) = rmse;
   set(ud(4),'Userdata',Rinv);
   set(ud(5),'Userdata',beta);
   set(ud(6),'Userdata',model);
   set(ud(10),'Userdata',residuals);
   set(lin_fig,'Userdata',ud);

   
elseif strcmp(action,'stray_click'),
   for k = 1:n,
      set(lin_fig,'CurrentAxes',lin_axes(k));
   end

end
