gusucode.com > 模糊控制工具箱 fuzzy logic toolbox源码程序 > fuzzy/fuzzy/ruleview.m

    function ruleview(action, input, figNumber);
%RULEVIEW Rule viewer and fuzzy inference diagram.
%   RULEVIEW(fis) opens the Rule Viewer, or Inference Diagram
%   Viewer, for the fuzzy inference system, fis. 
%   RULEVIEW('FILENAME') depicts the fuzzy inference 
%   diagram for the fuzzy inference system stored in file
%   FILENAME.FIS.
%
%   The Rule Viewer displays, in one screen, all parts of 
%   the fuzzy inference process from inputs to outputs. Each 
%   row of plots corresponds to one rule, and each column of 
%   plots corresponds to either an input variable (yellow, on 
%   the left) or an output variable (blue, on the right). You
%   can change the system input either by typing a specific 
%   value into the Input window or by moving the long yellow 
%   index lines that go down each input variable's column of 
%   plots.
%                                                                     
%   See also ADDRULE, MFEDIT, RULEEDIT, SURFVIEW

%   Ned Gulley, 3-30-94 Kelly Liu 4-20-97, N. Hickey 03-17-01
%   Copyright 1994-2004 The MathWorks, Inc.
%   $Revision: 1.63.2.2 $  $Date: 2004/04/10 23:15:36 $

inputColor=[1 0 0];
outputColor=[0 0 1];

if nargin<1,
    newFis=newfis('Untitled');
    newFis=addvar(newFis,'input','input1',[0 1],'init');
    newFis=addvar(newFis,'output','output1',[0 1],'init');
    action=newFis;
end

if isstr(action),
    if action(1)~='#',
        % The string "action" is not a switch for this function, 
        % so it must be a disk file
        fis=readfis(action);
        action='#initialize';
    end
else
    % For initialization, the fis matrix is passed in as the parameter
    fis=action;
    action='#initialize';
end;

if strcmp(action,'#initialize'),
    fisName=fis.name;
    numRules=length(fis.rule);
    thisfis{1}=fis;
    figNumber=figure( ...
        'Name',['Rule Viewer: ' fisName], ...
        'NumberTitle','off', ...
        'IntegerHandle','off',...
        'MenuBar','none', ...
        'Visible','off', ...
        'UserData',thisfis, ...
        'Tag','ruleview', ...
        'Color',[.9 .9 .9], ...
        'DoubleBuffer', 'on', ...
        'BackingStore','off', ...
        'DockControls', 'off');
    figPos=get(figNumber,'position');

    %====================================
    % The MENUBAR items
    % Call fisgui to create the menubar items
    fisgui #initialize

    %===================================
    % Information for all objects
    frmColor=192/255*[1 1 1];
    btnColor=192/255*[1 1 1];
    popupColor=192/255*[1 1 1];
    editColor=255/255*[1 1 1];
    border=6;
    spacing=6;
    maxRight=figPos(3);
    maxTop=figPos(4);
    btnWid=90;
    btnHt=22;

    bottom=border;
    top=bottom+2*btnHt+5*spacing;
    right=maxRight-border;
    left=border;
 
    %====================================
    % The MAIN frame
    % This frame is given a name so that it can be located later on
    % using "findobj". The UserData for this frame will contain the
    % matrix of line handles used in the callbacks.
    name='dataframe';
    frmBorder=spacing;
    frmPos=[left-frmBorder bottom-frmBorder ...
        right-left+frmBorder*2 top-bottom+frmBorder*2]+[1 0 1 0];
    frmHndl=uicontrol( ...
        'Style','frame', ...
        'Units','pixel', ...
        'Position',frmPos, ...
        'Tag',name, ...
        'BackgroundColor',frmColor);

    %====================================
    % The INPUT frame 
    top=top-spacing;
    bottom=top-btnHt;
    left=border+spacing;
    right=maxRight-border-1.5*btnWid-5*spacing;
    frmBorder=spacing;
    frmPos=[left-frmBorder bottom-frmBorder ...
        right-left-1.75*btnWid top-bottom+frmBorder*2]+[1 0 1 0];
    topFrmHndl=uicontrol( ...
        'Style','frame', ...
        'Units','pixel', ...
        'Position',frmPos, ...
        'BackgroundColor',frmColor);
    %-------numPts----------------------
    frmPos=[right-frmBorder-1.75*btnWid+.5*spacing bottom-frmBorder ...
        1.25*btnWid+1.5*spacing top-bottom+frmBorder*2]+[1 0 1 0];
    topFrmHndl=uicontrol( ...
        'Style','frame', ...
        'Units','pixel', ...
        'Position',frmPos, ...
        'BackgroundColor',frmColor);

    %------------------------------------
    % The num of points text window
    labelStr='Plot points:';
    pos1=[right-frmBorder-1.75*btnWid+spacing*1 bottom .78*btnWid btnHt];
    helpHndl=uicontrol( ...
        'Style','text', ...
        'BackgroundColor', frmColor, ...
        'HorizontalAlignment','left', ...
        'Units','pixel', ...
        'Position',pos1, ...
        'String',labelStr);
    %------------------------------------
    % The INPUT text window
    labelStr='Input:';
    pos=[left-spacing*.5 bottom btnWid/2 btnHt];
    helpHndl=uicontrol( ...
        'Style','text', ...
        'BackgroundColor',frmColor, ...
        'HorizontalAlignment','left', ...
        'Units','pixel', ...
        'Position',pos, ...
        'String',labelStr);

    %------------------------------------
    % The INPUT edit window
    callbackStr='ruleview #updateinputs';
    name='inputdisp';
    pos=[left+btnWid/2-2*spacing bottom right-left-btnWid*2.25 btnHt];
    inputDispHndl=uicontrol( ...
        'Style','edit', ...
        'BackgroundColor',editColor, ...
        'HorizontalAlignment','left', ...
        'Units','pixel', ...
        'Position',pos, ...
        'Tag',name, ...
        'Callback',callbackStr);
    %------------------------------------
    % The #points edit window
    name='numdisp';
    pos=[right-frmBorder-.85*btnWid-spacing*1 bottom .5*btnWid btnHt];
%pos1+[btnWid*.4 0 0 0];
    inputDispHndl=uicontrol( ...
        'Style','edit', ...
        'BackgroundColor',editColor, ...
        'HorizontalAlignment','left', ...
        'Units','pixel', ...
        'Position',pos, ...
        'Callback', 'ruleview #update',...
        'Tag',name);

    %====================================
    % The CLOSE/HELP frame 
    right=maxRight-border-spacing;
    left=right-2*btnWid-spacing;
    frmBorder=spacing;
    frmPos=[left-frmBorder bottom-frmBorder ...
        right-left+frmBorder*2 top-bottom+frmBorder*2]+[1 0 1 0];
    clsFrmHndl=uicontrol( ...
        'Style','frame', ...
        'Units','pixel', ...
        'Position',frmPos, ...
        'BackgroundColor',frmColor);
 
    frmPos=[left-frmBorder 7 ...
        right-left+frmBorder*2 top-bottom+frmBorder*2]+[1 0 1 0];
    clsFrmHndl=uicontrol( ...
        'Style','frame', ...
        'Units','pixel', ...
        'Position',frmPos, ...
        'BackgroundColor',frmColor);
    %------------------------------------
    % The postion text window
    pos1=[right-frmBorder-2*btnWid-spacing*.5 bottom 1.5*btnWid btnHt];
    helpHndl=uicontrol( ...
        'Style','text', ...
        'BackgroundColor',frmColor, ...
        'HorizontalAlignment','left', ...
        'Units','pixel', ...
        'Position',pos1, ...
        'String','Move:');

    %------------------------------------
    % The HELP button
    labelStr='Help';
    callbackStr='ruleview #help';
    helpHndl=uicontrol( ...
        'Style','push', ...
        'Position',[left bottom-40 btnWid btnHt], ...
        'BackgroundColor',btnColor, ...
        'String',labelStr, ...
        'Callback',callbackStr);

    %------------------------------------
    % The CLOSE button
    labelStr='Close';
    callbackStr='fisgui #close';
    closeHndl=uicontrol( ...
        'Style','push', ...
        'Position',[right-btnWid bottom-40 btnWid btnHt], ...
        'BackgroundColor',btnColor, ...
        'String',labelStr, ...
        'Callback',callbackStr);
    %------------------------------------
    % The shift horizontal button
    labelStr='left';
    callbackStr='ruleview #shiftleft';
    left=left+37;
    btnWid1= btnWid*2/5;
    closeHndl=uicontrol( ...
        'Style','push', ...
        'Position',[left 53 btnWid*2/5 btnHt], ...
        'BackgroundColor',btnColor, ...
        'String',labelStr, ...
        'Callback',callbackStr);

    % The shift horizontal button
    labelStr='right';
    callbackStr='ruleview #shiftright';
    closeHndl=uicontrol( ...
        'Style','push', ...
        'Position',[left+38 53 btnWid1 btnHt], ...
        'BackgroundColor',btnColor, ...
        'String',labelStr, ...
        'Callback',callbackStr);

    % The shift horizontal button
    labelStr='down';
    callbackStr='ruleview #shiftdown';
    closeHndl=uicontrol( ...
        'Style','push', ...
        'Position',[left+76 53 btnWid1 btnHt], ...
        'BackgroundColor',btnColor, ...
        'String',labelStr, ...
        'Callback',callbackStr);
    labelStr='up';
    callbackStr='ruleview #shiftup';
    closeHndl=uicontrol( ...
        'Style','push', ...
        'Position',[left+114 53 btnWid1 btnHt], ...
        'BackgroundColor',btnColor, ...
        'String',labelStr, ...
        'Callback',callbackStr);
%    callbackStr='ruleview #slidehori';
%    closeHndl=uicontrol( ...
%        'Style','slide', ...
%        'Position',[20 90 3*btnWid btnHt], ...
%        'Max', 2,...
%        'Min', -2,...
%        'Value', 0, ...
%        'BackgroundColor',btnColor, ...
%        'String',labelStr, ...
%        'Callback',callbackStr);


    %====================================
    bottom=border+spacing;


   % The STATUS frame 
    top=bottom+btnHt;
    right=maxRight-border-2*btnWid-5*spacing;

    left=border+spacing;
    frmBorder=spacing;
    frmPos=[left-frmBorder bottom-frmBorder ...
        right-left+frmBorder*2 top-bottom+frmBorder*2]+[1 0 1 0];
    dataFrmHndl=uicontrol( ...
        'Style','frame', ...
        'Units','pixel', ...
        'Position',frmPos, ...
        'BackgroundColor',frmColor);



    %------------------------------------
    % The STATUS text window
    labelStr=['Opened system ' fisName ', ' num2str(numRules) ' rules'];
    name='status';
    pos=[left bottom right-left btnHt];
    hndl=uicontrol( ...
        'Style','text', ...
        'BackgroundColor',frmColor, ...
        'HorizontalAlignment','left', ...
        'Units','pixel', ...
        'Position',pos, ...
        'Tag',name, ...
        'String',labelStr);

    ruleview #update

    % Normalize all coordinates
    hndlList=findobj(figNumber,'Units','pixels');
    set(hndlList,'Units','normalized');
 
    % Uncover the figure
    set(figNumber, ...
        'Visible','on', ...
        'HandleVisibility','callback');
       
elseif strcmp(action,'#update'),
    %====================================
    figNumber=watchon;
    oldfis=get(figNumber,'UserData');
    fis=oldfis{1};
    % Find and destroy all axes if they exist, since we might be updating
    % a previously existing system
    axHndlList=findobj(figNumber,'Type','axes');
    delete(axHndlList);
    set(figNumber,'Units','pixel')

    inputDispHndl=findobj(figNumber,'Type','uicontrol','Tag','inputdisp');
    set(inputDispHndl,'Enable','off');

    % First some error-checking
    if isfield(fis, 'input')
     numInputs=length(fis.input);
    else
     numInputs=0;
    end
    if isfield(fis, 'output')
     numOutputs=length(fis.output);
    else
     numOutputs=0;
    end
    if (numInputs<1) | (numOutputs<1),
        statmsg(figNumber,'Need at least one input and one output to view rules');
        watchoff(figNumber)
        return
    end
    numRules=length(fis.rule);
    if numRules<1,
        statmsg(figNumber,'Need at least one rule to view rules');
        watchoff(figNumber)
        return
    end

    border=6; 
    spacing=6;
    btnHt=22;
    figPos=get(figNumber,'Position');
    maxRight=figPos(3);
    maxTop=figPos(4);
    axColor='black';

    bottom=border;
    top=bottom+2*btnHt+5*spacing;
    right=maxRight-border;
 
    % The mainAxPos is a border that defines where the rules will be displayed
    % Getting it the right size was mostly trial and error
    mainAxPos=[border top-bottom+border*6 maxRight-border*2 maxTop-top-border*10];

    % Now build all the appropriate axes
    % For each rule, there will be as many axes as (numInputs+numOutputs)
    ruleList=getfis(fis, 'ruleList');
    numRules=size(ruleList,1);
    if isfield(fis, 'input')
     numInputs=length(fis.input);
    else
     numInputs=0;
    end
    if isfield(fis, 'output')
     numOutputs=length(fis.output);
    else
     numOutputs=0;
    end
    for i=1:numInputs
      numInputMFs(i)=length(fis.input(i).mf);
    end
    for i=1:numOutputs
      numOutputMFs(i)=length(fis.output(i).mf);
    end
    
    
    for i=1:numInputs
         inRange(i, 1:2)=fis.input(i).range;
    end

    for i=1:numOutputs
         outRange(i,1:2)=fis.output(i).range;
    end
    totalRange = [inRange;outRange];
    totalRange = totalRange + [totalRange(:,1) == totalRange(:,2)] * [-eps +eps];
    totalVars=numInputs+numOutputs;
    fisType=fis.type;

    boxWid=max((1/totalVars)*(maxRight-border*2), 30);
    boxHt=max((1/(numRules+3))*(maxTop-top-border*2), 10);
    xInset=boxWid/5;
    yInset=boxHt/10;

    % Here we're precalculating all MF x and y values for plotting later
    numPts=101;
    pthndl=findobj(gcf, 'Tag', 'numdisp');
    temp=str2double(get(pthndl, 'String'));
    if ~isempty(temp) & temp>=101
      numPts=temp;
    end
    [xIn,yIn,xOut,yOut,R]=discfis(fis,numPts);
    inputVector1=get(inputDispHndl,'Value');
    inputValidFlag=0;
    % If the previous value of the input vector is still valid, use it.
    if length(inputVector1)==numInputs,
        if all(inputVector1'>inRange(:,1)) & all(inputVector1'<inRange(:,2)),
            inputValidFlag=1;
        end
    end
    if inputValidFlag,
        inputVector=inputVector1;
    else
        inputVector=mean(inRange');
    end

    % Do the actual FIS evaluation
    numPts=101;
    pthndl=findobj(gcf, 'Tag', 'numdisp');
    temp=str2double(get(pthndl, 'String'));
    if ~isempty(temp) & temp>=101
      numPts=temp;
    else
      set(pthndl, 'String', num2str(numPts));
    end
    [v,irr,orr,arr]=evalfis(inputVector,fis, numPts);
    axHndlMat=zeros(numRules+1,totalVars);
    if strcmp(fisType,'sugeno'),
        sugenoOutputRange=sugmax(fis);
    end

    for ruleIndex=1:(numRules+1),
%        boxBtm=(rem(numRules+1-ruleIndex,(numRules+1))/(numRules+1))*mainAxPos(4)+ ...
%            mainAxPos(2);
        xInset2=xInset*0.1;
        yInset2=yInset*0.2;
        boxBtm= mainAxPos(2)+mainAxPos(4)-ruleIndex*(boxHt+yInset2); 
        for varIndex=1:totalVars,
%            boxLft=max((rem(varIndex-1,totalVars)/totalVars)*mainAxPos(3)+mainAxPos(1), mainAxPos(1)+(varIndex-1)*(boxWid+xInset2));
            boxLft=(rem(varIndex-1,totalVars)/totalVars)*mainAxPos(3)+mainAxPos(1);
            if (varIndex==1) & (ruleIndex<=numRules),
                %====================================
                % RULE NUMBER
                %====================================
                % Every rule number has its own axis
                axPos=[boxLft+xInset2 boxBtm+yInset+yInset2 ...
                    xInset-2*xInset2 boxHt-2*yInset-2*yInset2];
                axes( ...
                    'Units','pixel', ...
                    'Box','on', ...
                    'Visible','off', ...
                    'XTick',[],'YTick',[], ...
                    'XLim',[-1 1],'YLim',[-1 1], ...
                    'Position',axPos);
               text(0,0,num2str(ruleIndex), ...
                    'ButtonDownFcn','ruleview #disprule', ...
                    'FontSize',8, ...
                    'Tag','rulelabel', ...
                    'HorizontalAlignment','center');
            end

            axPos=[boxLft+xInset boxBtm+yInset boxWid-2*xInset boxHt-2*yInset];
            axHndlMat(ruleIndex,varIndex)=axes( ...
                'Units','pixel', ...
                'Box','on', ...
                'XColor',axColor,'YColor',axColor, ...
                'Xlim', totalRange(varIndex,:), 'Ylim', [-0.05 1.05], ...
                'XTick',[],'YTick',[], ...
                'Position',axPos);

            if (ruleIndex<=numRules) & (varIndex<=numInputs),
                %====================================
                % INPUT MFs
                %====================================
                % Here we are plotting the input variable membership functions
                % R is the modified rule list returned by discfis.
                mfColIndex=abs(R(ruleIndex,varIndex));
                % Use abs because negative refers to the use of NOT
                

                if mfColIndex,
                    % Don't plot it if the index is zero
                    x=xIn(:,mfColIndex);
                    y=yIn(:,mfColIndex);
                    if R(ruleIndex,varIndex)<0,
                        % Invert the MF if a NOT has been applied
                        y=1-y;
                    end
                    line(x,y,'Color',[.5 .5 0]);
                    xMin=min(x);
                    xMax=max(x);
                    xData=[xMin; x; xMax];
                    yData=min(irr(ruleIndex,varIndex),[0; y; 0]);
                    MFHndlMat(ruleIndex,varIndex)=patch( ...
                        xData,yData,[1 1 0]);
                end

                if ruleIndex==numRules, 
                    % Display the axis limits
                    set(gca,'XTick',totalRange(varIndex,:),'FontSize',8);
                end

            end

            if (ruleIndex<=numRules) & (varIndex>numInputs),
                %====================================
                % OUTPUT MFs
                %====================================
                % Here we are plotting the output variable membership functions
                % Remember the index may be negative
                outputVarIndex=varIndex-numInputs;
                % we have to subtract off the number of inputs since the
                % inputs are given before the outputs

                if ruleIndex==1, 
                    % Plot the variable name at the top of each column
                    varName=fis.output(varIndex-numInputs).name;
                    titleH=title([varName ' = ' num2str(v(varIndex-numInputs),3)], 'visible', 'on', 'fontSize', 8, 'interpreter','none');
                    set(gca, 'Tag', ['output' num2str(varIndex-numInputs)]);
                end

                mfIndex=abs(ruleList(ruleIndex,varIndex));
                if mfIndex,
                    % Plot it only if the index is nonzero
                    mfColIndex=sum(numOutputMFs(1:(outputVarIndex-1)))+mfIndex;
                    if strcmp(fisType,'mamdani'),
                        % MAMDANI system
                        x=xOut(:,mfColIndex);
                        y=yOut(:,mfColIndex);
                        if R(ruleIndex,varIndex)<0,
                            % Invert the MF if a NOT has been applied
                            y=1-y;
                        end
                        xMin=min(x);
                        xMax=max(x);
                        xData=[xMin; x; xMax];
                        yData=[0; orr(:,ruleIndex+(varIndex-numInputs-1)*numRules); 0];
                        MFHndlMat(ruleIndex,varIndex)=patch( ...
                            xData,yData,[.3 .3 1]);
                        line(x,y, ...
                             'Color',[0 0 .5]);
                    else
                        % SUGENO system
                        range=fis.output(varIndex-numInputs).range;
                        % The next line represents an educated guess at what the x axis
                        % limits should be
                        outRange=sugenoOutputRange(varIndex-numInputs,:);
                        outRange=outRange+0.1*(outRange(2)-outRange(1))*[-1 1];
                   %     outRange=.3*outRange;
                        outRange=eval(mat2str(outRange,4));
                        if outRange(1)==outRange(2)
                           outRange=outRange+[0 .1];
                        end
                        set(gca, ...
                            'XLim',outRange, ...
                            'YLim',[-0.05 1.05]);
                        xData2=[1 1]*orr(ruleIndex,varIndex-numInputs);
                        yData2=[0 1];
                        % The handle for the thin line will be carried by the fat line
                        lineHndl=line(xData2,yData2, ...
                            'LineWidth',5, ...
                            'LineStyle','-', ...
                            'Visible','on', ...
                            'Color',[.6 .8 .8]);
                        xData1=xData2;
                        yData1=[0 1]*arr(ruleIndex,varIndex-numInputs);
                        MFHndlMat(ruleIndex,varIndex)=line(xData1,yData1, ...
                            'LineWidth',4, ...
                            'UserData',lineHndl, ...
                            'Color',[0 0 1]);
                    end
                end
            end

            if (ruleIndex>numRules) & (varIndex<=numInputs),
                %====================================
                % MOVEABLE INDEX LINES
                %====================================
                % Draw in moveable input index lines
                % This axes position covers all axes in this input column
 %       boxBtm= mainAxPos(2)+mainAxPos(4)-ruleIndex*(10*yInset+yInset2); 
%                axPos=[boxLft+xInset mainAxPos(2) boxWid-2*xInset mainAxPos(4)];
                axPos=[boxLft+xInset boxBtm+yInset boxWid-2*xInset ruleIndex*(10*yInset+yInset2)];
                colIndex=sum(numInputMFs(1:(varIndex-1)))+1;
                xMin=inRange(varIndex,1);
                xMax=inRange(varIndex,2);
                inputVal=inputVector(varIndex);
                set(gca, ...
                    'Units','pixel', ...
                    'Visible','off', ...                  
                    'XLim',[xMin xMax],'YLim',[0 1], ...
                    'Position',axPos);
                line([1 1]*inputVal,[0.01 1], ...
                    'LineWidth',0.5, ...
                    'Color',[1 0 0], ...
                    'ButtonDownFcn','ruleview #clickline', ...
                    'UserData',varIndex, ...
                    'Tag','indexline', ...
                    'LineStyle','-');
                % The following patch is used to allow click-anywhere 
                % positioning of the index line
                patchHndl=patch([xMin xMax xMax xMin xMin],[0 0 1 1 0],'black');
                set(patchHndl, ...
                    'ButtonDownFcn','ruleview #patchclick', ...
                    'FaceColor','none', ...
                    'EdgeColor','none');
                if ruleIndex==numRules+1, 
                    % Plot the variable name at the top of each column
                    varName=fis.input(varIndex).name;
                    title([varName ' = ' num2str(inputVal,3)], 'visible', 'on', 'fontSize', 8, 'interpreter','none')
                end

            end

            if (ruleIndex>numRules) & (varIndex>numInputs),
                %====================================
                % AGGREGATE MF PLOT
                %====================================
                varName=fis.output(varIndex-numInputs).name;
                mfColIndex=sum(numOutputMFs(1:(varIndex-numInputs-1)))+1;
                if mfColIndex<=size(xOut,2),
                    x=xOut(:,mfColIndex);
                else
                    x=zeros(size(arr,1),1);
                end
%                compStr=computer;
%                if compStr(1:2)=='PC',
%                    eraseMode='normal';
%                else
%                    eraseMode='background';
%                end     
%                xlabel(num2str(v(varIndex-numInputs),3), ...
%                    'FontSize',8,'EraseMode',eraseMode);
                if strcmp(fisType,'mamdani'),
                    % MAMDANI
                    xMin=outRange(varIndex-numInputs,1);
                    xMax=outRange(varIndex-numInputs,2);
                    set(gca, ...
                        'XLim',totalRange(varIndex,:),'YLim',[-0.1 1.1], ...
                        'XTick',totalRange(varIndex,:), ...
                        'FontSize',8, ...
                        'XColor','b','YColor','b')
                    xData=[xMin; x; xMax];
                    yData=[0; arr(:,varIndex-numInputs); 0];
                    MFHndlMat(ruleIndex,varIndex)=patch( ...
                        xData,yData,[.3 .3 1]);
                    line(v(varIndex-numInputs)*[1 1],[-0.05 1.05], ...
                        'Color',[1 0 0], ...
                        'MarkerSize',12, ...
                        'LineWidth',3)
                else
                    % SUGENO system
                    set(gca, ...
                        'XLim',outRange, ...
                        'YLim',[-0.05 1.05], ...
                        'XTick',outRange, ...
                        'XColor','black','YColor','black')
                    lineHndl=line(v(varIndex-numInputs)*[1 1],[-0.05 1.05], ...
                        'Color',[1 0 0], ...
                        'MarkerSize',15, ...
                        'LineWidth',2);

                    xData=orr(:,varIndex-numInputs)';
                    xData=[xData; xData; NaN*ones(size(xData))];
                    yData=arr(:,varIndex-numInputs)';
                    yData=[zeros(size(yData)); yData; NaN*ones(size(yData))];

                    MFHndlMat(ruleIndex,varIndex)=line(xData(:),yData(:), ...
                        'LineWidth',4, ...
                        'UserData',lineHndl, ...
                        'Color',[.3 .3 1]);
                end
            end
        end
    end

    % The UserData will contain the varIndex to simplify 
    % calculations later on.
    set(inputDispHndl, ...
        'Value',inputVector, ...
        'String',[' ' mat2str(inputVector,4)]);

    % Get handles to axes for plotting
    frameName='dataframe';
    dataFrmHndl=findobj(figNumber,'Type','uicontrol', ...
        'Style','frame','Tag',frameName);
    set(dataFrmHndl,'UserData',MFHndlMat);

    % Normalize all coordinates
    hndlList=findobj(figNumber,'Units','pixels');
    set(hndlList,'Units','normalized');
 
    set(inputDispHndl,'Enable','on');
    watchoff(figNumber)

elseif strcmp(action,'#clickline'),
    %====================================
    figNumber=gcf;
    set(figNumber,'WindowButtonMotionFcn','ruleview #dragline');
    set(figNumber,'WindowButtonUpFcn','ruleview #updateinputs');
    ruleview #dragline

elseif strcmp(action,'#dragline'),
    %====================================
    lineHndl=gco;
    axHndl=get(lineHndl,'Parent');
    textHndl1=get(axHndl,'Title');
    ptMat=get(axHndl,'CurrentPoint');
    x=ptMat(1,1);
    xLims=get(axHndl,'XLim');
    if (x < xLims(1)),
        x=xLims(1);
    elseif (x > xLims(2)),
        x=xLims(2);
    end
    set(lineHndl,'XData',[x x]);
    oldtext = get(textHndl1, 'String');
    stopn=find(oldtext=='=');
    set(textHndl1,'String',[oldtext(1:stopn),' ', num2str(x(1),3)]);
% Uncomment the following lines if you want to see continuous update
% during a line drag
%    ruleview #updateinputs
%    set(figNumber,'WindowButtonMotionFcn','ruleview #dragline');
%    set(figNumber,'WindowButtonUpFcn','ruleview #updateinputs');

elseif strcmp(action,'#updateinputs'),
    %====================================
    figNumber=gcf;
    oldfis=get(figNumber,'UserData');
    fis=oldfis{1};
    if isfield(fis, 'input')
     numInputs=length(fis.input);
    else
     numInputs=0;
    end
    if isfield(fis, 'output')
     numOutputs=length(fis.output);
    else
     numOutputs=0;
    end

    if strcmp(get(gco,'Type'),'line'),
        % We're here because the moveable line indices have been moved
        lineHndl=gco;
        xData=get(lineHndl,'XData');
        varIndex=get(lineHndl,'UserData');
        inputDispHndl=findobj(figNumber,'Type','uicontrol','Tag','inputdisp');
        inputVector=get(inputDispHndl,'Value');
        inputVector(varIndex)=xData(1);
        set(inputDispHndl,'Value',inputVector);
        set(inputDispHndl,'String',[' ' mat2str(inputVector,4)]);    
    else
        % We're here because the input vector text field has been changed
        inputDispHndl=gco;

        % Error-checking
        % The backupInputVector is the previous (or safety) value
        backupInputVector=get(inputDispHndl,'Value');
        % Use try-catch eval statement to keep out ASCII trash

        newInputStr=get(inputDispHndl,'String');
        % We'll put the brackets in later; no point in dealing with the hassle
        index=[find(newInputStr=='[') find(newInputStr==']')];
        newInputStr(index)=32*ones(size(index));
        newInputStr=['[' newInputStr ']'];

        % Use eval try-catch to prevent really weird stuff...
        inputVector=eval(newInputStr,'backupInputVector');
        if length(inputVector)<numInputs,
            inputVector=backupInputVector;
        else
            inputVector=inputVector(1:numInputs);
        end

        for i=1:numInputs
         inRange(i, 1:2)=fis.input(i).range;
        end
        
        for count=1:numInputs,
            % Find the appropriate index line
            indexLineHndl=findobj(figNumber, ...
                'Type','line','Tag','indexline','UserData',count);
            textHndl=get(get(indexLineHndl,'Parent'),'Title');
            xLims=inRange(count,:);

            % Check to make sure each input is within its limits
            if (inputVector(count) < xLims(1)),
                inputVector(count)=xLims(1);
            elseif (inputVector(count) > xLims(2)),
                inputVector(count)=xLims(2);
            end
            set(indexLineHndl,'XData',inputVector(count)*[1 1]);
            oldtext=get(textHndl,'String');
            textn=find(oldtext=='=');
            set(textHndl,'String',[oldtext(1:textn), ' ', num2str(inputVector(count),3)]);
        end

        set(inputDispHndl,'Value',inputVector);
        set(inputDispHndl,'String',[' ' mat2str(inputVector,4)]);
    end
   
    % Get handles to axes for plotting
    frameName='dataframe';
    dataFrmHndl=findobj(figNumber,'Type','uicontrol', ...
        'Style','frame','Tag',frameName);
    MFHndlMat=get(dataFrmHndl,'UserData');

    % Remove the button motion and button up functions
    set(figNumber,'WindowButtonMotionFcn',' ');
    set(figNumber,'WindowButtonUpFcn',' ');
    numPts=101;
    pthndl=findobj(gcf, 'Tag', 'numdisp');
    temp=str2double(get(pthndl, 'String'));
    if ~isempty(temp) & temp>=101
      numPts=temp;
    end

    [v,IRR,ORR,ARR]=evalfis(inputVector,fis, numPts);
    numRules=length(fis.rule);
    fisType=fis.type;
    %====================================
    % Update INPUTS (we only need to update ONE of the inputs)
    for ruleIndex=1:numRules,
        for varIndex=1:numInputs,
            % If the handle is zero, then the plot doesn't exist, so
            % don't mess with anything
            if MFHndlMat(ruleIndex,varIndex),
                axHndl=get(MFHndlMat(ruleIndex,varIndex),'Parent');
                lineHndl=findobj(axHndl,'Type','line');
                yData=get(lineHndl,'YData');
                yData=min(yData,IRR(ruleIndex,varIndex));
                yData=[0 yData 0];

                set(MFHndlMat(ruleIndex,varIndex), ...
                    'YData',yData);
            end
        end
    end

    %====================================
    % Update OUTPUTS
    if strcmp(fisType,'mamdani'),
        % MAMDANI system
        % Update individual rule output displays (implication)
        for ruleIndex=1:numRules
            for varIndex=(1:numOutputs)+numInputs,
                yData=ORR(:,ruleIndex+(varIndex-numInputs-1)*numRules);
                yData=[0 yData' 0];
                lineHndl=MFHndlMat(ruleIndex,varIndex);
                if ruleIndex==1
                  axHndl=findobj(gcbf, 'Tag', ['output' num2str(varIndex-numInputs)]);
                  titleHndl=get(axHndl,'Title');
                  oldtext=get(titleHndl,'String');
                  if ~isempty(oldtext)
                    textn=find(oldtext=='=');
                  else
                    textn=[];
                  end
                  set(titleHndl,'Visible', 'on', 'String',[oldtext(1:textn), ' ', num2str(v(varIndex-numInputs),3)], 'fontSize', 8);
                end
                if lineHndl,
                    % Don't update it if it doesn't exist
                    set(lineHndl,'YData',yData);
                end
            end
        end

        % Update aggregate output display
        for varIndex=(1:numOutputs)+numInputs,
            patchHndl=MFHndlMat(numRules+1,varIndex);
            axHndl=get(patchHndl,'Parent');
            yData=ARR(:,varIndex-numInputs);
            yData=[0 yData' 0];
            set(patchHndl, ...
                'YData',yData);
            lineHndl=findobj(axHndl,'Type','line');
            set(lineHndl,'XData',v(varIndex-numInputs)*[1 1]);
        end
    else
        % SUGENO system
        for ruleIndex=1:numRules
            for varIndex=(1:numOutputs)+numInputs,
                thickLineHndl=MFHndlMat(ruleIndex,varIndex);
                % Don't update it if it doesn't exist
                if thickLineHndl,
                    thinLineHndl=get(MFHndlMat(ruleIndex,varIndex),'UserData');
                    xData2=[1 1]*ORR(ruleIndex,varIndex-numInputs);
                    set(thinLineHndl,'XData',xData2);
                    yData=[0 1]*ARR(ruleIndex,varIndex-numInputs);
                    set(MFHndlMat(ruleIndex,varIndex), ...
                        'XData',xData2,'YData',yData);
                if ruleIndex==1
                  axHndl=get(thinLineHndl,'Parent');
                  titleHndl=get(axHndl,'Title');
                  oldtext=get(titleHndl,'String');
                  textn=find(oldtext=='=');
                  set(titleHndl,'Visible', 'on', 'String',[oldtext(1:textn), ' ', num2str(v(varIndex-numInputs),3)]);
                end
                end
            end
        end

        % Update aggregate output display
        for varIndex=(1:numOutputs)+numInputs,
            xData=ORR(:,varIndex-numInputs)';
            xData=[xData; xData; NaN*ones(size(xData))];
            yData=ARR(:,varIndex-numInputs)';
            yData=[zeros(size(yData)); yData; NaN*ones(size(yData))];

            lineHndl1=MFHndlMat(numRules+1,varIndex);
            set(lineHndl1, ...
                'XData',xData(:),'YData',yData(:));

            % Now reposition the output index line
            lineHndl2=get(lineHndl1,'UserData');
            xData2=v(varIndex-numInputs)*[1 1];
            set(lineHndl2,'XData',xData2);
        end
    end

elseif strcmp(action,'#patchclick'),
    %====================================
    patchHndl=gco;
    figNumber=gcf;
    axHndl=get(patchHndl,'Parent');
    lineHndl=findobj(axHndl,'Type','line');
    set(figNumber,'CurrentObject',lineHndl);
    ruleview #clickline

elseif strcmp(action,'#input'),
    %====================================
    inputHndl=gco;
    figNumber=gcf;

elseif strcmp(action,'#disprule'),
    %====================================
    % Display the rule that the user has clicked on
    txtHndl=gco;
    figNumber=gcf;
    selectColor=[1 0 0];

    % Find and reset any previously highlighted rules
    oldTxtHndl=findobj(figNumber,'Type','text','Tag','rulelabel','FontSize',14);
    if length(oldTxtHndl)>0,
        set(oldTxtHndl,'Color','black','FontSize',8,'FontWeight','normal');
    end
    set(txtHndl,'Color',selectColor,'FontSize',14,'FontWeight','bold');

    % Find out what display format is preferred
    formatHndl=findobj(figNumber,'Type','uimenu','Tag','dispformat');
    dispFormat=get(findobj(formatHndl,'Checked','on'),'Tag');
    oldfis=get(figNumber,'UserData');
    fis=oldfis{1};
    ruleIndexStr=get(txtHndl,'String');
    ruleIndex=str2double(ruleIndexStr);
    if strcmp(dispFormat,'indexed'),
        ruleStr=['Rule ' num2str(ruleIndex) '. ' showrule(fis,ruleIndex,'indexed')];
    else
        ruleStr=['Rule ' showrule(fis,ruleIndex,dispFormat)];
    end
    % The next line is a workaround to make sure that the "|" character will display
    % properly in a text uicontrol
    ruleStr=str2mat(ruleStr,' ');
    statmsg(figNumber,ruleStr);

elseif strcmp(action,'#dispformat');
    %====================================
    figNumber=watchon;
    currHndl=gcbo;
    verHndl=findobj(figNumber,'Type','uimenu','Tag','verbose');
    symHndl=findobj(figNumber,'Type','uimenu','Tag','symbolic');
    indHndl=findobj(figNumber,'Type','uimenu','Tag','indexed');
    set([verHndl symHndl indHndl],'Checked','off');
    set(currHndl,'Checked','on');
    watchoff(figNumber)
elseif strcmp(action, '#shiftleft')
    axesHndl=findobj(gcbf, 'Type','axes');
    pos=get(axesHndl, 'Position');
    for i=1:length(pos)
     set(axesHndl(i), 'Position', pos{i}-[.05 0 0 0]);
    end
elseif strcmp(action, '#shiftright')
    axesHndl=findobj(gcbf, 'Type','axes');
    pos=get(axesHndl, 'Position');
    for i=1:length(pos)
     set(axesHndl(i), 'Position', pos{i}+[.05 0 0 0]);
    end
elseif strcmp(action, '#shiftup')
    axesHndl=findobj(gcbf, 'Type','axes');
    pos=get(axesHndl, 'Position');
    for i=1:length(pos)
     set(axesHndl(i), 'Position', pos{i}+[0 0.05 0 0]);
    end
elseif strcmp(action, '#shiftdown')
    axesHndl=findobj(gcbf, 'Type','axes');
    pos=get(axesHndl, 'Position');
    for i=1:length(pos)
     set(axesHndl(i), 'Position', pos{i}-[0 .05 0 0]);
    end
elseif strcmp(action, '#slidehori')
    Hndl=gcbo;
    value=get(gcbo, 'Value');
    axesHndl=findobj(gcbf, 'Type','axes');
    pos=get(axesHndl, 'Position');
    for i=1:length(pos)
     newpos=pos{i};
     newpos(1)=value;
     set(axesHndl(i), 'Position', newpos);
    end

elseif strcmp(action,'#help');
    figNumber=watchon;
     helpwin(mfilename);
    watchoff(figNumber)
elseif strcmp(action,'#simulink');
%    figNumber=gcf;
    oldfis=get(figNumber,'UserData');
    fis=oldfis{1};
    if isfield(fis, 'input')
     numInputs=length(fis.input);
    else
     numInputs=0;
    end
    if isfield(fis, 'output')
     numOutputs=length(fis.output);
    else
     numOutputs=0;
    end

        % We're here because the input vector text field has been changed

        % Error-checking
        % The backupInputVector is the previous (or safety) value
        % Use try-catch eval statement to keep out ASCII trash

        inputVector=input;

        for i=1:numInputs
         inRange(i, 1:2)=fis.input(i).range;
        end
        
        for count=1:numInputs,
            % Find the appropriate index line
            indexLineHndl=findobj(figNumber, ...
                'Type','line','Tag','indexline','UserData',count);
            textHndl=get(get(indexLineHndl,'Parent'),'title');
            xLims=inRange(count,:);

            % Check to make sure each input is within its limits
            if (inputVector(count) < xLims(1)),
                inputVector(count)=xLims(1);
            elseif (inputVector(count) > xLims(2)),
                inputVector(count)=xLims(2);
            end
            set(indexLineHndl,'XData',inputVector(count)*[1 1]);
            oldtext=get(textHndl,'String');
            textn=find(oldtext=='=');
            set(textHndl,'String',[oldtext(1:textn), ' ', num2str(inputVector(count),3)]);

            set(indexLineHndl,'XData',inputVector(count)*[1 1]);
%            set(textHndl,'String',num2str(inputVector(count),3), 'Visible', 'on');
        end
        inputDispHndl=findobj(figNumber, 'Tag', 'inputdisp');
        set(inputDispHndl,'Value',inputVector);
        set(inputDispHndl,'String',[' ' mat2str(inputVector,4)]);

   
    % Get handles to axes for plotting
    frameName='dataframe';
    dataFrmHndl=findobj(figNumber,'Type','uicontrol', ...
        'Style','frame','Tag',frameName);
    MFHndlMat=get(dataFrmHndl,'UserData');

    % Remove the button motion and button up functions
    set(figNumber,'WindowButtonMotionFcn',' ');
    set(figNumber,'WindowButtonUpFcn',' ');
    numPts=101;
    pthndl=findobj(gcf, 'Tag', 'numdisp');
    tempstr=get(pthndl, 'String');
    temp=[];
    if ~isempty(tempstr)
     temp=str2double(get(pthndl, 'String'));
    end
    if ~isempty(temp) & temp>=101
      numPts=temp;
    end
    [v,IRR,ORR,ARR]=evalfis(inputVector,fis, numPts);
    numRules=length(fis.rule);
    fisType=fis.type;
   %====================================
    % Update INPUTS (we only need to update ONE of the inputs)
    for ruleIndex=1:numRules,
        for varIndex=1:numInputs,
            % If the handle is zero, then the plot doesn't exist, so
            % don't mess with anything
            if MFHndlMat(ruleIndex,varIndex),
                axHndl=get(MFHndlMat(ruleIndex,varIndex),'Parent');
                lineHndl=findobj(axHndl,'Type','line');
                yData=get(lineHndl,'YData');
                yData=min(yData,IRR(ruleIndex,varIndex));
                yData=[0 yData 0];

                set(MFHndlMat(ruleIndex,varIndex), ...
                    'YData',yData);
            end
        end
    end

    %====================================
    % Update OUTPUTS
    if strcmp(fisType,'mamdani'),
        % MAMDANI system
        % Update individual rule output displays (implication)
        for ruleIndex=1:numRules
            for varIndex=(1:numOutputs)+numInputs,
                yData=ORR(:,ruleIndex+(varIndex-numInputs-1)*numRules);
                yData=[0 yData' 0];
                lineHndl=MFHndlMat(ruleIndex,varIndex);
                if ruleIndex==1
                  axHndl=get(lineHndl,'Parent');
                  titleHndl=get(axHndl,'Title');
                  oldtext=get(titleHndl,'String');
                  textn=find(oldtext=='=');
                  set(titleHndl, 'String',[oldtext(1:textn), ' ', num2str(v(varIndex-numInputs),3)], 'fontSize', 8);
                end
                if lineHndl,
                    % Don't update it if it doesn't exist
                    set(lineHndl,'YData',yData);
                end
            end
        end

        % Update aggregate output display
        for varIndex=(1:numOutputs)+numInputs,
            patchHndl=MFHndlMat(numRules+1,varIndex);
            axHndl=get(patchHndl,'Parent');
            yData=ARR(:,varIndex-numInputs);
            yData=[0 yData' 0];
            set(patchHndl, ...
                'YData',yData);
            lineHndl=findobj(axHndl,'Type','line');
            set(lineHndl,'XData',v(varIndex-numInputs)*[1 1]);
        end
    else
        % SUGENO system
        for ruleIndex=1:numRules
            for varIndex=(1:numOutputs)+numInputs,
                thickLineHndl=MFHndlMat(ruleIndex,varIndex);
                % Don't update it if it doesn't exist
                if thickLineHndl,
                    thinLineHndl=get(MFHndlMat(ruleIndex,varIndex),'UserData');
                    xData2=[1 1]*ORR(ruleIndex,varIndex-numInputs);
                    set(thinLineHndl,'XData',xData2);
                    yData=[0 1]*ARR(ruleIndex,varIndex-numInputs);
                    set(MFHndlMat(ruleIndex,varIndex), ...
                        'XData',xData2,'YData',yData);
                end
                if ruleIndex==1
                  axHndl=get(thickLineHndl,'Parent');
                  titleHndl=get(axHndl,'Title');
                  oldtext=get(titleHndl,'String');
                  textn=find(oldtext=='=');
                  set(titleHndl, 'String',[oldtext(1:textn), ' ', num2str(v(varIndex-numInputs),3)], 'fontSize', 8);
                end
            end
        end

        % Update aggregate output display
        for varIndex=(1:numOutputs)+numInputs,
            xData=ORR(:,varIndex-numInputs)';
            xData=[xData; xData; NaN*ones(size(xData))];
            yData=ARR(:,varIndex-numInputs)';
            yData=[zeros(size(yData)); yData; NaN*ones(size(yData))];

            lineHndl1=MFHndlMat(numRules+1,varIndex);
            set(lineHndl1, ...
                'XData',xData(:),'YData',yData(:));

            % Now reposition the output index line
            lineHndl2=get(lineHndl1,'UserData');
            xData2=v(varIndex-numInputs)*[1 1];
            set(lineHndl2,'XData',xData2);
        end
    end
       
end;    % if strcmp(action, ...