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

    function varargout = poles( m, action, varargin )
%XREGARX/POLES   Plot the poles of a dynamic lolimot model
%   FIGH = POLES(M,'Figure',NAME,TSAMPLE) displays a  window for viewing the 
%   poles of the linear submodels (betamodels) of the dynamic lolimot model M. 
%   NAME is an optional string containing the model name to be displayed in 
%   the title bar of the window. TSAMPLE is the time in seconds for each sample 
%   and is also optional. It is used to calculate the time constant for the 
%   poles.
%
%   POLES(M,'Enable') returns true of false to indicate whether this pole 
%   viewer is available for the given dynamic lolimot model M.
%
%   [LYT,UD] = POLES(M,'Layout',FIGH)

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


if nargin < 1,
    error(message('mbc:xregdynlolimot:InvalidArgument5'));
end

if nargin < 2,
    action = 'Figure';
end

switch lower( action ),
    case 'enable',
        varargout{1} = i_IsLinearLolimot( m );
    case 'figure',
        varargout{1} = i_CreateDialog( m, varargin{:} );
    case 'layout',
        [varargout{1}, varargout{2}] = i_CreateLayout( m, varargin{:} );
    otherwise
        error(message('mbc:xregdynlolimot:InvalidArgument6', action));
end

return

%------------------------------------------------------------------------------|
function en = i_IsLinearLolimot( m )
% en is a 0/1 flag which to enable/disable the menu item on the main MBC Browser

% Must have a feedback term
if m.delmat(1,end) == 0,
    en = 0;
    return
end

% To be able to enable ploting of the poles all the beta models must be linear
bm = get( m, 'BetaModels' );

ncent = size( get( m, 'centers' ), 1 );
bmc = cell( 1, ncent );
for i=1:ncent,
    bmc{i} = name( bm{i} );
end
bmc = unique( bmc );

en = ( length( bmc ) == 1 ) & ...
    ( strcmpi( bmc, 'linear' ) | strcmpi( bmc, 'xreglinear' ) );

return

%------------------------------------------------------------------------------|
function figh = i_CreateDialog( m, modelname, tsample )
i_deleteold

if nargin < 2,
    modelname = '';
end
if nargin < 3,
    tsample = 1;
end

figh = xregfigure('Tag', i_hash_fig_tag,...
    'Name', sprintf( 'LOLIMOT Poles: %s', modelname ),...
    'Visible', 'Off' );
xregcenterfigure( figh, [600, 450] ); 
figh.MinimumSize = [600, 450];

[lyt, ud] = i_CreateLayout( m, figh );
ud.model = m;
ud.tsample = tsample;

btnClose = uicontrol( 'Parent', figh,...
    'Style', 'PushButton',...
    'String', 'Close',...
    'Interruptible', 'off',...
    'Callback', 'set( gcbf, ''visible'', ''off'' );' );

DividerLine = xregGui.dividerline( figh );

lyt = xreggridbaglayout( figh, ...
    'Dimension',[3, 3],...
    'RowSizes',[-1, 2, 25 ],...
    'ColSizes',[-1, 65, 65],...
    'GapY',5,...
    'GapX',7,...
    'Border',[5, 5, 5, 5],...
    'MergeBlock', { [1, 1], [1, 3] }, ...
    'MergeBlock', { [2, 2], [1, 3] }, ...
    'Elements', { ...
        lyt, [], []; ...
        DividerLine, [], []; ...
        [], [], btnClose } ); 
    
% tell the figure about all the data associated with it
set( figh, 'UserData', ud );

% Initialization
i_clickModel( [], [], figh );
   
%
% All ready, turn it on
figh.LayoutManager = lyt;
set( lyt, 'packstatus', 'on' );
set( figh, 'Visible', 'on' );

% we wait for the user to close the window
%%delete( figh );

return
%------------------------------------------------------------------------------|
function [lyt, ud] = i_CreateLayout( m, figh )

%  +---------------------------------------------------+
%  | Local Model  <[     ]>  [Plot][Table]             |
%  | +--------------------+  +----+------+-----------+ |
%  | |     Center  Width  |  |                       | |
%  | | x1  [    ]  [    ] |  |                       | |
%  | | x2  [    ]  [    ] |  |                       | |
%  | | y1  [    ]  [    ] |  |                       | |
%  | |                    |  |                       | |
%  | +--------------------+  +-----------------------+ |
%  +---------------------------------------------------+

BackgroundColor = get( figh, 'Color' );
ncent = get( m, 'NumberOfCenters' );
symbols = get( m, 'Symbols' );
nf = length( symbols );

ud.clickModel = mbcgui.widget.Spinner( 'Parent', figh, ...
    'Min', 1, ...
    'Max', ncent, ...
    'ClickIncrement', 1, ...
    'Visible', 'on', ...
    'Callback', { @i_clickModel, figh } );

lctrlModel = xregGui.labelcontrol( ...
    'parent',figh,...
    'Control', ud.clickModel,...
    'String','Local Model',...
    'Enable','on', ...
    'ControlSize', 100, ...
    'ControlSizeMode', 'absolute');

% center and width display table
ud.tableCenterWidth = xregtable( figh,...
    'frame.visible', 'off',...
    'frame.hborder', [0, 0],...
    'frame.vborder', [0, 0],...
    'defaultcellformat', '%.4f',...
    'defaultcelltype', 'uiedit',...
    'cols.size', 55,...
    'cols.spacing', 2,...
    'rows.spacing', 2,...
    'cells.defaultinterruptible', 'off',...
    'cells.defaultbackgroundcolor', [1, 1, 1],...
    'zeroindex', [2, 2],...
     ... % Title row
    'cells.rowselection', [1, 1],...
    'cells.colselection', [1, 3],...
    'cells.type', 'uitext',...
    'cells.string', {'', 'Center', 'Width'},...
    'cells.horizontalalignment', 'center',...
    'cells.fontweight', 'normal',...
    'cells.backgroundcolor', BackgroundColor,...
    'rows.fixed', 1,...
    ... % Symbol name column
    'cells.rowselection', [2, nf+1],...
    'cells.colselection', [1, 1],...
    'cells.type', 'uitext',...
    'cells.string', symbols,...
    'cells.horizontalalignment', 'left',...
    'cells.backgroundcolor', BackgroundColor,...
    'cols.fixed', 1, ...
    ... % Center and width columns
    'cells.rowselection', [2, nf+1],...
    'cells.colselection', [2, 3],...
    'cells.type', 'uiedit',...
    'cells.enable', 'inactive',...
    'cells.horizontalalignment', 'right' );
ud.tableCenterWidth.redrawmode = 'normal';

tablyt = uitabgroup('Parent',figh,...
    'Units','pixels');
axesTab = mbcgui.container.uitab('Parent',tablyt,...
    'Title','Plot');

% This layout provides a bit of a border around the axes to allow room for the 
% TickLabels.
lytAxes = mbcgui.widget.AxesContainer('AxesHandle', axesTab, ...
    'PositionSetting','outer',...
    'Border', [30 30 5 5]);
ud.axesPols = lytAxes.AxesHandle;
set(ud.axesPoles , ...
    'Box', 'on',...
    'XGrid', 'on',...
    'YGrid', 'on', ...
    'XLimMode', 'Manual', ... 
    'YLimMode', 'Manual', ...
    'XLim', [-1.5, 1.5], ...
    'YLim', [-1.5, 1.5], ...
    'XTick', 0, ...
    'YTick', 0, ...
    'PlotBoxAspectRatioMode', 'Manual', ...
    'PlotBoxAspectRatio', [1, 1, 1] );
axesTab.LayoutComponent = lytAxes;

t = linspace( -pi, pi, 200 );
line( ...
    'Parent', ud.axesPoles, ...
    'XData', cos( t ), ...
    'YData', sin( t ), ...
    'Color', 'k', ...
    'LineStyle', ':', ...
    'LineWidth', 0.5, ...
    'Marker', 'none' );

ud.linePoles = line( ...
    'Parent', ud.axesPoles, ...
    'XData', [], ...
    'YData', [], ...
    'LineStyle', 'none', ...
    'LineWidth', 3.0, ... % really the width of the marker edge
    'Marker', 'x', ...
    'MarkerEdgeColor', 'r', ...
    'MarkerFaceColor', 'r', ...
    'MarkerSize', 12, ...
    'ButtonDownFcn', { @i_linePoles, figh } );

tableTab = mbcgui.container.uitab('Parent',tablyt,...
    'Title','Table');


% table for pole display
ud.tablePoles = xregtable(tableTab,...
    'visible', 'on',...
    'frame.visible', 'off',...
    'frame.hborder', [0, 0],...
    'frame.vborder', [0, 0],...
    'defaultcellformat', '%.4f',...
    'defaultcelltype', 'uiedit',...
    'cols.size', 65,...
    'cols.spacing', 2,...
    'rows.spacing', 2,...
    'cells.defaultinterruptible', 'off',...
    'cells.defaultbackgroundcolor', [1, 1, 1],...
    'zeroindex', [2, 1],...
     ... % Title row
    'cells.rowselection', [1, 1],...
    'cells.colselection', [1, 5],...
    'cells.type', 'uitext',...
    'cells.string', {'Real', 'Imag.', 'Magnitude', 'Angle', 'Time Const.'},...
    'cells.horizontalalignment', 'center',...
    'cells.fontweight', 'normal',...
    'cells.backgroundcolor', BackgroundColor,...
    'rows.fixed', 1 );
ud.tablePoles.redrawmode = 'normal';

lytTablePoles = xregborderlayout( tableTab, ...
    'Border', [5, 5, 5, 5], ... % [W, S, E, N]
    'Center', ud.tablePoles );
tableTab.LayoutComponent = lytTablePoles;

% overall window layout
lyt = xreggridbaglayout(figh, ...
    'Dimension',[2, 2],...
    'RowSizes',[20, -1 ],...
    'ColSizes',[200, -1],...
    'GapY',5,...
    'GapX',7,...
    'Border',[5, 5, 5, 5],...
    'MergeBlock', { [1, 2], [2, 2] }, ...
    'Elements', { ...
        lctrlModel, tablyt; ...
        ud.tableCenterWidth, [] } ); 

return

%------------------------------------------------------------------------------|
function i_clickModel( src, ~, figh )
ud = get( figh, 'UserData' );
m = ud.model;

if isempty( src ), 
    src = ud.clickModel;
end

% What is the local model to display?
ind = get( src, 'Value' );

% Display centers, widths associated with that local model
table = ud.tableCenterWidth;
nf = nfactors( m );
centers = get( m, 'Centers' );
width = get( m, 'Width' );

table(1:nf,1) = transpose( centers(ind,:) );
table(1:nf,2) = transpose(   width(ind,:) ); %#ok<NASGU>

% Display poles for that model
i_DisplayPoles( ud )

return
%------------------------------------------------------------------------------|
function i_linePoles( src, ~, figh )
% src is the line object
ud = get( figh, 'UserData' );
axh = ud.axesPoles;

% find where the user clicked
cp = get( axh, 'CurrentPoint' );
cp = cp(1,[1,2]); % only need x- any y-coordinates

%
% Find closet data points to where user clicked
%
% get coorindates of data points 
XData = get( src, 'XData' );
YData = get( src, 'YData' );

% find all data points within 1/40 of the plot size of currentPoint
accuracy = 40;
XTol = diff( get( axh, 'XLim' ) ) /accuracy;
YTol = diff( get( axh, 'YLim' ) ) /accuracy;
ind = find( abs( XData - cp(1) ) < XTol & abs( YData - cp(2) ) < YTol );

% sometimes the patch appears with no data
if isempty(ind)
    disp( 'No points nearby' )
    % at worst, show the two points that were very near to cp
    [~, xind] = min( abs( XData - cp(1) ) );
    [~, yind] = min( abs( YData - cp(2) ) );
    ind = [xind, yind];
end

ind = unique( ind );

%
% Setup string
%
p = XData(ind) + 1i * YData(ind);
if length( p ) == 1,
    if isreal( p ),
        str1 = sprintf( 'Pole       = %.4g', real( p ) );
    else
        str1 = sprintf( 'Pole       = %.4g %+.4gi', real( p ), imag( p ) );
    end
    str = char( ...
        str1, ...
        sprintf( 'Magnitude  = %.4g', abs( p ) ), ...
        sprintf( 'Angle      = %d deg', round( 180 * angle( p )/ pi ) ), ... 
        sprintf( 'Time const = %.4g s', ud.tsample ./ abs( p ) ), ...
        '' );
else
    str = char( ...
        'Real part ', ...
        'Imag part ', ...
        'Magnitude ', ...
        'Angle     ', ...
        'Time const' );
    for ii = 1:length( p ),
        str = cat( 2,  str, blanks( 5 )', char( ...
            num2str( real( p(ii) ), 4 ), ...
            num2str( imag( p(ii) ), 4 ), ...
            num2str( abs( p(ii) ), 4 ), ...
            num2str( round( 180 * angle( p(ii) )/ pi ), 4 ), ...
            num2str( ud.tsample ./ abs( p(ii) ), 4 ), ...
            '' ) );
    end
end

%
% Display the patch
%
i_TextPatch( axh, str, cp );

return

%------------------------------------------------------------------------------|
function i_DisplayPoles( ud )

m = ud.model;
bm = get( m, 'BetaModels' );
delmat = get( m, 'delmat' );
order = delmat(1,end);
delay = delmat(2,end);

ind = get( ud.clickModel, 'Value' );

beta = double( bm{ind} );
beta = beta(end-order+1:end);

% y(k) - b(1) y(k-1) - ... - b(q) y(k-q) = f( x1(k), ..., xn(k-p) )
% ==> want the zeros of  z^q - b(1) x^(q-1) - ... - b(q)
p = roots( [1, zeros( 1, delay-1 ), -beta(:)'] );

set( ud.linePoles, 'XData', real( p ) );
set( ud.linePoles, 'YData', imag( p ) );

ind = 1:length(p);
ud.tablePoles(ind,1) = real( p );
ud.tablePoles(ind,2) = imag( p );
ud.tablePoles(ind,3) = abs( p );
ud.tablePoles(ind,4) = 180 * angle( p )/ pi; % convert to degrees
ud.tablePoles(ind,5) = ud.tsample ./ abs( p ); % time const

return

%---------------------------------|--------------------------------------------|
function i_TextPatch( ax, infoStr, CP )
% taken from mbcmodels/validate_rstool

xmode =    get(ax,'XLimMode');
ymode =    get(ax,'YLimMode');
set(ax,'XLimMode','manual','YLimMode','manual','Layer','bottom')
% save old ax units
oldUnits=get(ax,'Units');

commonUnit = 'point';

%create the text to find out its extent and hence if it fits in the figure
ph=patch('FaceColor',[1 1 0.8],...
    'Parent',ax,...
    'Visible','off',...
    'EdgeColor','k',...
    'Tag','dataPatch',...
    'FaceAlpha',1,...
    'Clipping','off');

th=text(CP(1),CP(2),3.0,infoStr,...
   'Units','data',...
   'Visible','off',...
   'Parent',ax,...
   'FontName','Lucida Console',...
   'Clipping','off',...
   'HorizontalAlignment','left',...
   'VerticalAlignment','bottom',...
   'Interpreter','none');        

% everything in same units (commonUnit) to see if it all fits on 
set([ax,th],'Units',commonUnit);
Apos=get(ax,'Position'); % =ax pos in commonUnit
axW = Apos(3);
axH = Apos(4);

% sort out text size (a bit!)
maxFontSize = 8; %in 'point'
fsize= min(axH/size(infoStr,1),maxFontSize);
fsize= min(fsize,1.7*axW/size(infoStr,2));
% set text fontsize in 'point'
set(th,'FontSize',fsize);
% now find how much space the text takes up
ext = get(th,'Extent');

if (ext(1)+ext(3))>axW %% goes off axes right
   if (ext(1)-ext(3))<0 %% will go off left if we right-align text
      Tpos = get(th,'Position');
      set(th,'Position',[0, Tpos(2)]);
   else
      set(th,'HorizontalAlignment','right');
   end
end

if (ext(2)+ext(4))>axH %% goes off axes top
   if (ext(2)-ext(4))<0 %% goes off bottom
      Tpos = get(th,'Position');
      set(th,'Position',[Tpos(1),0]);
   else
      set(th,'VerticalAlignment','top');
   end
end

% revert to original units
set(ax,'Units',oldUnits);
set(th,'Units','data');
ex=get(th,'Extent');
set(ph,...
    'XData', [ex(1), ex(1), ex(1)+ex(3), ex(1)+ex(3)],...
    'YData', [ex(2), ex(2)+ex(4), ex(2)+ex(4), ex(2)],...
    'ZData', repmat( 2.0, [1,4] ) );

oldUpFcn = get(gcbf ,'WindowButtonUpFcn');
set(gcbf, 'WindowButtonUpFcn', ...
    { @i_killtextpatch, ph, th, xmode, ymode, oldUpFcn } );
set([th,ph],'Visible','on');

return

%---------------------------------|--------------------------------------------|
function i_killtextpatch(~, ~, ph, th, xmode, ymode, oldUpFcn)
% Remove text and patch
% taken from mbcmodels/validate_rstool

set(get(ph,'Parent'),'XLimMode',xmode,'YLimMode',ymode)
set(gcbf ,'WindowButtonUpFcn',oldUpFcn);
delete(ph);
delete(th);

return

%------------------------------------------------------------------------------|
function i_deleteold
h = findobj( allchild(0), 'flat', 'Tag', i_hash_fig_tag );
if ~isempty( h )
   delete( h );
end
return

%------------------------------------------------------------------------------|
function s = i_hash_fig_tag
s = 'XregdynlolimotPoles';
return