Home > reduc > plotting > subplot2.m

subplot2

PURPOSE ^

SUBPLOT Create axes in tiled positions.

SYNOPSIS ^

function theAxis = subplot2(nrows, ncols, thisPlot, varargin)

DESCRIPTION ^

SUBPLOT Create axes in tiled positions.
This version puts more space around images and is more suitable for
figures containing many subplots
 CJC 30/9/2010
   H = SUBPLOT(m,n,p), or SUBPLOT(mnp), breaks the Figure window
   into an m-by-n matrix of small axes, selects the p-th axes for
   the current plot, and returns the axis handle.  The axes are
   counted along the top row of the Figure window, then the second
   row, etc.  For example,

       SUBPLOT(2,1,1), PLOT(income)
       SUBPLOT(2,1,2), PLOT(outgo)

   plots income on the top half of the window and outgo on the
   bottom half. If the CurrentAxes is nested in a uipanel the
   panel is used as the parent for the subplot instead of the
   current figure.

   SUBPLOT(m,n,p), if the axis already exists, makes it current.
   SUBPLOT(m,n,p,'replace'), if the axis already exists, deletes it and
   creates a new axis.
   SUBPLOT(m,n,p,'align') places the axes so that the plot boxes 
   are aligned, but does not prevent the labels and ticks from 
   overlapping.
   SUBPLOT(m,n,P), where P is a vector, specifies an axes position
   that covers all the subplot positions listed in P.
   SUBPLOT(H), where H is an axis handle, is another way of making
   an axis current for subsequent plotting commands.

   SUBPLOT('position',[left bottom width height]) creates an
   axis at the specified position in normalized coordinates (in
   in the range from 0.0 to 1.0).

   SUBPLOT(..., PROP1, VALUE1, PROP2, VALUE2, ...) sets the
   specified property-value pairs on the subplot axis. To add the
   subplot to a specific figure pass the figure handle as the
   value for the 'Parent' property.

   If a SUBPLOT specification causes a new axis to overlap an
   existing axis, the existing axis is deleted - unless the position
   of the new and existing axis are identical.  For example,
   the statement SUBPLOT(1,2,1) deletes all existing axes overlapping
   the left side of the Figure window and creates a new axis on that
   side - unless there is an axes there with a position that exactly
   matches the position of the new axes (and 'replace' was not specified),
   in which case all other overlapping axes will be deleted and the
   matching axes will become the current axes.

   SUBPLOT(111) is an exception to the rules above, and is not
   identical in behavior to SUBPLOT(1,1,1).  For reasons of backwards
   compatibility, it is a special case of subplot which does not
   immediately create an axes, but instead sets up the figure so that
   the next graphics command executes CLF RESET in the figure
   (deleting all children of the figure), and creates a new axes in
   the default position.  This syntax does not return a handle, so it
   is an error to specify a return argument.  The delayed CLF RESET
   is accomplished by setting the figure's NextPlot to 'replace'.

   Be aware when creating subplots from scripts that the Position
   property of subplots is not finalized until either a drawnow
   command is issued, or MATLAB returns to await a user command. 
   That is, the value obtained for subplot i by the command 
   get(h(i),'Position') will not be correct until the script
   refreshes the plot or exits. 

   See also  GCA, GCF, AXES, FIGURE, UIPANEL

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function theAxis = subplot2(nrows, ncols, thisPlot, varargin)
0002 %SUBPLOT Create axes in tiled positions.
0003 %This version puts more space around images and is more suitable for
0004 %figures containing many subplots
0005 % CJC 30/9/2010
0006 %   H = SUBPLOT(m,n,p), or SUBPLOT(mnp), breaks the Figure window
0007 %   into an m-by-n matrix of small axes, selects the p-th axes for
0008 %   the current plot, and returns the axis handle.  The axes are
0009 %   counted along the top row of the Figure window, then the second
0010 %   row, etc.  For example,
0011 %
0012 %       SUBPLOT(2,1,1), PLOT(income)
0013 %       SUBPLOT(2,1,2), PLOT(outgo)
0014 %
0015 %   plots income on the top half of the window and outgo on the
0016 %   bottom half. If the CurrentAxes is nested in a uipanel the
0017 %   panel is used as the parent for the subplot instead of the
0018 %   current figure.
0019 %
0020 %   SUBPLOT(m,n,p), if the axis already exists, makes it current.
0021 %   SUBPLOT(m,n,p,'replace'), if the axis already exists, deletes it and
0022 %   creates a new axis.
0023 %   SUBPLOT(m,n,p,'align') places the axes so that the plot boxes
0024 %   are aligned, but does not prevent the labels and ticks from
0025 %   overlapping.
0026 %   SUBPLOT(m,n,P), where P is a vector, specifies an axes position
0027 %   that covers all the subplot positions listed in P.
0028 %   SUBPLOT(H), where H is an axis handle, is another way of making
0029 %   an axis current for subsequent plotting commands.
0030 %
0031 %   SUBPLOT('position',[left bottom width height]) creates an
0032 %   axis at the specified position in normalized coordinates (in
0033 %   in the range from 0.0 to 1.0).
0034 %
0035 %   SUBPLOT(..., PROP1, VALUE1, PROP2, VALUE2, ...) sets the
0036 %   specified property-value pairs on the subplot axis. To add the
0037 %   subplot to a specific figure pass the figure handle as the
0038 %   value for the 'Parent' property.
0039 %
0040 %   If a SUBPLOT specification causes a new axis to overlap an
0041 %   existing axis, the existing axis is deleted - unless the position
0042 %   of the new and existing axis are identical.  For example,
0043 %   the statement SUBPLOT(1,2,1) deletes all existing axes overlapping
0044 %   the left side of the Figure window and creates a new axis on that
0045 %   side - unless there is an axes there with a position that exactly
0046 %   matches the position of the new axes (and 'replace' was not specified),
0047 %   in which case all other overlapping axes will be deleted and the
0048 %   matching axes will become the current axes.
0049 %
0050 %   SUBPLOT(111) is an exception to the rules above, and is not
0051 %   identical in behavior to SUBPLOT(1,1,1).  For reasons of backwards
0052 %   compatibility, it is a special case of subplot which does not
0053 %   immediately create an axes, but instead sets up the figure so that
0054 %   the next graphics command executes CLF RESET in the figure
0055 %   (deleting all children of the figure), and creates a new axes in
0056 %   the default position.  This syntax does not return a handle, so it
0057 %   is an error to specify a return argument.  The delayed CLF RESET
0058 %   is accomplished by setting the figure's NextPlot to 'replace'.
0059 %
0060 %   Be aware when creating subplots from scripts that the Position
0061 %   property of subplots is not finalized until either a drawnow
0062 %   command is issued, or MATLAB returns to await a user command.
0063 %   That is, the value obtained for subplot i by the command
0064 %   get(h(i),'Position') will not be correct until the script
0065 %   refreshes the plot or exits.
0066 %
0067 %   See also  GCA, GCF, AXES, FIGURE, UIPANEL
0068 
0069 %   SUBPLOT(m,n,p,H) when H is an axes will move H to the specified
0070 %   position.
0071 %   SUBPLOT(m,n,p,H,PROP1,VALUE1,...) will move H and apply the
0072 %   specified property-value pairs
0073 %
0074 %   SUBPLOT(m,n,p) for non-integer p places the subplot at the
0075 %   fraction p-floor(p) between the positions floor(p) and ceil(p)
0076 
0077 %   Copyright 1984-2008 The MathWorks, Inc.
0078 %   $Revision: 1.1 $  $Date: 2010/09/30 15:42:44 $
0079 
0080 narg = nargin;
0081 
0082 % First we check whether Handle Graphics uses MATLAB classes
0083 isHGUsingMATLABClasses = feature('HGUsingMATLABClasses');
0084 
0085 % Next we check whether we should ignore a possible v6 argument.
0086 if isHGUsingMATLABClasses && narg >= 4 && ~ischar(nrows)
0087     arg = varargin{1};
0088     if ischar(arg) && strcmpi(arg,'v6')
0089         warning(['MATLAB:', mfilename, ':IgnoringV6Argument'],...
0090             ['Ignoring the ''v6'' argument to %s.',...
0091             '  This will become an error in a future release.'], upper(mfilename));
0092         narg = narg - 1;
0093         varargin(1) = [];
0094     end
0095 end
0096 
0097 % we will kill all overlapping axes siblings if we encounter the mnp
0098 % or m,n,p specifier (excluding '111').
0099 % But if we get the 'position' or H specifier, we won't check for and
0100 % delete overlapping siblings:
0101 kill_siblings = 0;
0102 create_axis = true;
0103 move_axis = false;
0104 delay_destroy = false;
0105 useAutoLayout = true;
0106 tol = sqrt(eps);
0107 parent = get(0,'CurrentFigure');
0108 parentfigure = parent;
0109 if ~isempty(parent) && ~isempty(get(parent,'CurrentAxes'))
0110     parent = get(get(parent,'CurrentAxes'),'Parent');
0111     parentfigure = parent;
0112     if ~strcmp(get(parentfigure,'Type'),'figure')
0113         parentfigure = ancestor(parent,'figure');
0114     end
0115 end
0116 pvpairs = {};
0117 preventMove = false;
0118 % This is the percent offset from the subplot grid of the plotbox.
0119 inset = [.2 .18 .04 0.6]; % [left bottom right top]
0120 
0121 if narg == 0 % make compatible with 3.5, i.e. subplot == subplot(111)
0122     nrows = 111;
0123     narg = 1;
0124 end
0125 
0126 %check for encoded format
0127 handle = '';
0128 position = '';
0129 explicitParent = false;
0130 explicitPosition = false;
0131 
0132 if narg == 1
0133     % The argument could be one of 3 things:
0134     % 1) a 3-digit number 100 < num < 1000, of the format mnp
0135     % 2) a 3-character string containing a number as above
0136     % 3) an axis handle
0137     code = nrows;
0138 
0139     % turn string into a number:
0140     if(ischar(code))
0141         code = str2double(code);
0142     end
0143     
0144     % Check for NaN and Inf.
0145     if (~isfinite(code))
0146         error(id('SubplotIndexNonFinite'),'Index must be a finite 3-digit number of the format mnp.')
0147     end
0148 
0149     % number with a fractional part can only be an identifier:
0150     if(rem(code,1) > 0)
0151         handle = code;
0152         if ~strcmp(get(handle,'type'),'axes')
0153             error(id('InvalidAxesHandle'),'Requires valid axes handle for input.')
0154         end
0155         create_axis = false;
0156         % all other numbers will be converted to mnp format:
0157     else
0158         % Check for input out of range
0159         if (code <= 100 || code >= 1000)
0160             error(id('SubplotIndexOutOfRange'),'Index must be a 3-digit number of the format mnp.')
0161         end
0162         
0163         thisPlot = rem(code, 10);
0164         ncols = rem( fix(code-thisPlot)/10,10);
0165         nrows = fix(code/100);
0166         if nrows*ncols < thisPlot
0167             error(id('SubplotIndexTooLarge'),'Index exceeds number of subplots.');
0168         end
0169         kill_siblings = 1;
0170         if(code == 111)
0171             create_axis   = false;
0172             delay_destroy = true;
0173         else
0174             create_axis   = true;
0175             delay_destroy = false;
0176         end
0177     end
0178 
0179 elseif narg == 2
0180     % The arguments MUST be the string 'position' and a 4-element vector:
0181     if(strcmpi(nrows, 'position'))
0182         pos_size = size(ncols);
0183         if(pos_size(1) * pos_size(2) == 4)
0184             position = ncols;
0185             explicitPosition = true;
0186         else
0187             error(id('InvalidPositionParameter'),...
0188                 'Position must be of the form [left bottom width height].')
0189         end
0190     else
0191         error(id('UnknownOption'),'Unknown command option.')
0192     end
0193     kill_siblings = 1; % Kill overlaps here also.
0194     useAutoLayout = false;
0195 
0196 elseif narg == 3
0197     % passed in subplot(m,n,p) -- we should kill overlaps
0198     % here too:
0199     kill_siblings = 1;
0200 
0201 elseif narg >= 4
0202     if ~ischar(nrows)
0203         arg = varargin{1};
0204         if ~ischar(arg)
0205             % passed in subplot(m,n,p,H,...)
0206             handle = arg;
0207             parent = get(handle,'Parent');
0208             parentfigure = ancestor(handle,'figure');
0209             % If the parent is passed in explicitly, don't create a new figure
0210             % when the "NextPlot" property is set to "new" in the figure.
0211             explicitParent = true;
0212             set(parentfigure,'CurrentAxes',handle);
0213             move_axis = true;
0214             create_axis = false;
0215             if narg >= 5 && strcmpi(varargin{2},'PreventMove')
0216                 preventMove = true;
0217                 pvpairs = varargin(3:end);
0218             else
0219                 pvpairs = varargin(2:end);
0220             end
0221         elseif strncmpi(arg,'replace',1)
0222             % passed in subplot(m,n,p,'replace')
0223             kill_siblings = 2; % kill nomatter what
0224         elseif strcmpi(arg,'align')
0225             % passed in subplot(m,n,p,'align')
0226             % since obeying position will remove the axes from the grid just set
0227             % useAutoLayout to false to skip adding it to the grid to start with
0228             useAutoLayout = false;
0229             kill_siblings = 1; % kill if it overlaps stuff
0230         elseif strcmpi(arg,'v6')
0231             % passed in subplot(m,n,p,'v6')
0232             % since obeying position will remove the axes from the grid just set
0233             % useAutoLayout to false to skip adding it to the grid to start with
0234             warning(['MATLAB:', mfilename, ':DeprecatedV6Argument'],...
0235                 ['The ''v6'' argument to %s is deprecated,',...
0236                 ' and will no longer be supported in a future release.'], upper(mfilename));
0237             useAutoLayout = false;
0238             kill_siblings = 1; % kill if it overlaps stuff
0239         else
0240             % passed in prop-value pairs
0241             kill_siblings = 1;
0242             pvpairs = varargin;
0243             par = find(strncmpi('Parent',pvpairs(1:2:end),6));
0244             if any(par)
0245                 % If the parent is passed in explicitly, don't create a new figure
0246                 % when the "NextPlot" property is set to "new" in the figure.
0247                 explicitParent = true;
0248                 parent = varargin{2*par(1)};
0249                 parentfigure = ancestor(parent,'figure');
0250             end
0251         end
0252     else
0253         % Passed in "Position" syntax with P/V pairs
0254         % The arguments MUST be the string 'position' and a 4-element vector:
0255         if(strcmpi(nrows, 'position'))
0256             pos_size = size(ncols);
0257             if(pos_size(1) * pos_size(2) == 4)
0258                 position = ncols;
0259                 explicitPosition = true;
0260             else
0261                 error(id('InvalidPositionParameter'),...
0262                     'Position must be of the form [left bottom width height].')
0263             end
0264         else
0265             error(id('UnknownOption'),'Unknown command option.')
0266         end
0267         kill_siblings = 1; % Kill overlaps here also.
0268         useAutoLayout = false;
0269         pvpairs = [{thisPlot} varargin];
0270         par = find(strncmpi('Parent',pvpairs(1:2:end),6));
0271         if any(par)
0272             % If the parent is passed in explicitly, don't create a new figure
0273             % when the "NextPlot" property is set to "new" in the figure.
0274             explicitParent = true;
0275             parent = pvpairs{2*par(1)};
0276             parentfigure = ancestor(parent,'figure');
0277         end
0278     end
0279 end
0280 
0281 % if we recovered an identifier earlier, use it:
0282 if ~isempty(handle) && ~move_axis
0283     parent = get(handle,'Parent');
0284     parentfigure = ancestor(handle,'figure');
0285     set(parentfigure,'CurrentAxes',handle);
0286 else  % if we haven't recovered position yet, generate it from mnp info:
0287     if isempty(parent),
0288         parent = gcf;
0289         parentfigure = parent;
0290     end
0291     if isempty(position)
0292         if min(thisPlot) < 1
0293             error(id('SubplotIndexTooSmall'),'Illegal plot number.')
0294         elseif max(thisPlot) > ncols*nrows
0295             error(id('SubplotIndexTooLarge'),'Index exceeds number of subplots.');
0296         else
0297 
0298             row = (nrows-1) -fix((thisPlot-1)/ncols);
0299             col = rem (thisPlot-1, ncols);
0300 
0301             % get default axis position in normalized units
0302             % If we have checked this quanitity once, cache it.
0303             if ~isappdata(parentfigure,'SubplotDefaultAxesLocation')
0304                 if ~strcmp(get(parentfigure,'defaultaxesunits'),'normalized')
0305                     tmp = axes;
0306                     set(tmp,'units','normalized')
0307                     def_pos = get(tmp,'position');
0308                     delete(tmp)
0309                 else
0310                     def_pos = get(parentfigure,'DefaultAxesPosition');
0311                 end
0312                 setappdata(parentfigure,'SubplotDefaultAxesLocation',def_pos);
0313             else
0314                 def_pos = getappdata(parentfigure,'SubplotDefaultAxesLocation');
0315             end
0316 
0317             % compute outerposition and insets relative to figure bounds
0318             rw = max(row)-min(row)+1;
0319             cw = max(col)-min(col)+1;
0320             width = def_pos(3)/(ncols - inset(1) - inset(3));
0321             height = def_pos(4)/(nrows - inset(2) - inset(4));
0322             inset = inset.*[width height width height];
0323             outerpos = [def_pos(1) + min(col)*width - inset(1), ...
0324                 def_pos(2) + min(row)*height - inset(2), ...
0325                 width*cw height*rw];
0326 
0327             % adjust outerpos and insets for axes around the outside edges
0328             if min(col) == 0
0329                 inset(1) = def_pos(1);
0330                 outerpos(3) = outerpos(1)+outerpos(3);
0331                 outerpos(1) = 0;
0332             end
0333             if min(row) == 0,
0334                 inset(2) = def_pos(2);
0335                 outerpos(4) = outerpos(2)+outerpos(4);
0336                 outerpos(2) = 0;
0337             end
0338             if max(col) == ncols-1,
0339                 inset(3) = max(0,1-def_pos(1)-def_pos(3));
0340                 outerpos(3) = 1-outerpos(1);
0341             end
0342             if max(row) == nrows-1,
0343                 inset(4) = max(0,1-def_pos(2)-def_pos(4));
0344                 outerpos(4) = 1-outerpos(2);
0345             end
0346 
0347             % compute inner position
0348             position = [outerpos(1:2) + inset(1:2),...
0349                 outerpos(3:4) - inset(1:2) - inset(3:4)];
0350 
0351         end
0352     end
0353 end
0354 
0355 % kill overlapping siblings if mnp specifier was used:
0356 nextstate = get(parentfigure,'nextplot');
0357 
0358 if strncmp(nextstate,'replace',7)
0359     nextstate = 'add';
0360 elseif strncmp(nextstate,'new',3)
0361     kill_siblings = 0;
0362 end
0363 
0364 if(kill_siblings)
0365     if delay_destroy
0366         if nargout
0367             error(id('TooManyOutputs'),...
0368                 'Function called with too many output arguments.')
0369         else
0370             set(parentfigure,'NextPlot','replace');
0371             return
0372         end
0373     end
0374     sibs = datachildren(parent);
0375     newcurrent = [];
0376     for i = 1:length(sibs)
0377         % Be aware that handles in this list might be destroyed before
0378         % we get to them, because of other objects' DeleteFcn callbacks...
0379         if(ishghandle(sibs(i),'axes'))
0380             units = get(sibs(i),'Units');
0381             sibpos = get(sibs(i),'Position');
0382             % If a legend or colorbar has resized the axes, use the original axes
0383             % position as the "Position" property:
0384             if ~explicitPosition
0385                 if isappdata(sibs(i),'LegendColorbarExpectedPosition') && ...
0386                         isequal(getappdata(sibs(i),'LegendColorbarExpectedPosition'),get(sibs(i),'Position'))
0387                     inset = getappdata(sibs(i),'LegendColorbarOriginalInset');
0388                     if isempty(inset)
0389                         % during load the appdata might not be present
0390                         inset = get(get(sibs(i),'Parent'),'DefaultAxesLooseInset');
0391                     end
0392                     inset = offsetsInUnits(sibs(i),inset,'normalized',get(sibs(i),'Units'));
0393                     if strcmpi(get(sibs(i),'ActivePositionProperty'),'position')
0394                         pos = get(sibs(i),'Position');
0395                         loose = get(sibs(i),'LooseInset');
0396                         opos = getOuterFromPosAndLoose(pos,loose,get(sibs(i),'Units'));
0397                         if strcmp(get(sibs(i),'Units'),'normalized')
0398                             inset = [opos(3:4) opos(3:4)].*inset;
0399                         end
0400                         sibpos = [opos(1:2)+inset(1:2) opos(3:4)-inset(1:2)-inset(3:4)];
0401                     end
0402                 end
0403             end
0404             if ~strcmp(units,'normalized')
0405                 sibpos = hgconvertunits(parentfigure,sibpos,units,'normalized',parent);
0406             end
0407             intersect = 1;
0408             if((position(1) >= sibpos(1) + sibpos(3)-tol) || ...
0409                     (sibpos(1) >= position(1) + position(3)-tol) || ...
0410                     (position(2) >= sibpos(2) + sibpos(4)-tol) || ...
0411                     (sibpos(2) >= position(2) + position(4)-tol))
0412                 intersect = 0;
0413             end
0414             if intersect
0415                 % position is the proposed position of an axes, and
0416                 % sibpos is the current position of an existing axes.
0417                 % Since the bounding boxes of position and sibpos overlap,
0418                 % we must determine whether to delete the sibling sibs(i)
0419                 % whose normalized position is sibpos.
0420                 
0421                 % First of all, we check whether we must kill the sibling
0422                 % "no matter what."
0423                 if (kill_siblings == 2)
0424                     delete(sibs(i));
0425                     
0426                 % If the proposed and existing axes overlap exactly, we do
0427                 % not kill the sibling.  Rather we shall ensure later that
0428                 % this sibling axes is set as the 'CurrentAxes' of its
0429                 % parentfigure.
0430                     
0431                 % Next we check for a partial overlap.
0432                 elseif (any(abs(sibpos - position) > tol))
0433                     % The proposed and existing axes partially overlap.
0434                     % Since the proposed and existing axes could each be
0435                     % "grid-generated" or "explicitly-specified", we must
0436                     % consider four possibilities for the overlap of
0437                     % "proposed" vs. "existing", i.e.
0438                     % (1) "grid-generated" vs. "grid-generated"
0439                     % (2) "grid-generated" vs. "explicitly-specified"
0440                     % (3) "explicitly-specified" vs. "grid-generated"
0441                     % (4) "explicitly-specified" vs. "explicitly-specified"
0442                     
0443                     % If the position of the proposed axes is
0444                     % "explicitly-specified", then the only condition that
0445                     % avoids killing the sibling is an exact overlap.
0446                     % However, we know that the overlap is partial.
0447                     if (explicitPosition)
0448                         delete(sibs(i));
0449                     else
0450                         % We know that the position of the proposed axes is
0451                         % "grid-generated".
0452                         
0453                         grid = getappdata(parent,'SubplotGrid');
0454                         % The SubplotGrid maintains an array of axes
0455                         % handles, one per grid location.  Axes that span
0456                         % multiple grid locations do not store handles in
0457                         % the SubplotGrid.
0458                         
0459                         if isempty(grid) || ~any(grid(:) == sibs(i)) || ...
0460                                 size(grid,1) ~= nrows || size(grid,2) ~= ncols || ...
0461                                 ~isscalar(row) || ~isscalar(col)
0462                             % If the sibling cannot be found in the grid, we
0463                             % kill the sibling.  Otherwise, the proposed and
0464                             % existing axes are "grid-generated".  If we
0465                             % are changing the size of the grid, we kill
0466                             % the sibling.  Otherwise, "thisPlot" may be a
0467                             % vector of multiple grid locations, which
0468                             % causes a partial overlap between the proposed
0469                             % and existing axes, so we kill the sibling.
0470                             
0471                             % This check recognizes that there may be
0472                             % labels, colorbars, legends, etc. attached to
0473                             % the existing axes that have affected its
0474                             % position.  In such a case, we do not kill the
0475                             % sibling.
0476                             delete(sibs(i));
0477                         end
0478                     end
0479                 end
0480                 if ishghandle(sibs(i))
0481                     % if this axes overlaps the other one exactly then
0482                     if ~isempty(newcurrent) && ishghandle(newcurrent)
0483                         delete(newcurrent);
0484                     end
0485                     newcurrent = sibs(i);
0486                 end
0487             end
0488         end
0489     end
0490     if ~isempty(newcurrent) && ishghandle(newcurrent)
0491         set(parentfigure,'CurrentAxes',newcurrent);
0492         create_axis = false;
0493     end
0494     set(parentfigure,'NextPlot',nextstate);
0495 end
0496 
0497 % create the axis:
0498 if create_axis
0499     if strcmp(nextstate,'new') && ~explicitParent
0500         parent = figure;
0501         parentfigure = parent;
0502     end
0503     ax = axes('units','normal','Position',position,...
0504         'LooseInset',inset,'Parent',parent);
0505     % TODO: Get axes to accept position args on command line
0506     set(ax,'units',get(double(parentfigure),'defaultaxesunits'))
0507     if useAutoLayout
0508         addAxesToGrid(ax,nrows,ncols,row,col,position);
0509     end
0510     if ~isempty(pvpairs)
0511         set(ax,pvpairs{:});
0512     end
0513 elseif move_axis && ~preventMove
0514     ax = handle;
0515     units = get(handle,'units');
0516     set(handle,'units','normal','Position',position,...
0517         'LooseInset',inset,'Parent',parent);
0518     set(handle,'units',units);
0519     if useAutoLayout
0520         addAxesToGrid(ax,nrows,ncols,row,col,position);
0521     end
0522     if ~isempty(pvpairs)
0523         set(handle,pvpairs{:});
0524     end
0525 else
0526     % this should only happen with subplot(H)
0527     ax = get(parentfigure,'CurrentAxes');
0528 end
0529 
0530 % return identifier, if requested:
0531 if(nargout > 0)
0532     theAxis = ax;
0533 end
0534 
0535 % Create subplot listeners to align plot boxes automatically
0536 function createListeners(p,axlisth)
0537 setappdata(p,'SubplotListeners',[])
0538 fig = p;
0539 if ~isequal(get(fig,'Type'),'figure')
0540     fig = ancestor(fig,'figure');
0541 end
0542 list = [...
0543     handle.listener(axlisth,findprop(axlisth(1),'Units'), ... % must be first
0544     'PropertyPostSet',@axesUnitsPostSet);
0545     handle.listener(axlisth,findprop(axlisth(1),'Units'), ...
0546     'PropertyPreSet',@axesUnitsPreSet);
0547     handle.listener(axlisth,findprop(axlisth(1),'Position'), ...
0548     'PropertyPostSet',@axesMoved);
0549     handle.listener(axlisth,findprop(axlisth(1),'ActivePositionProperty'), ...
0550     'PropertyPreSet',@axesMoved);
0551     handle.listener(axlisth,findprop(axlisth(1),'Parent'), ...
0552     'PropertyPreSet',@axesMoved);
0553     handle.listener(axlisth,'AxisInvalidEvent',{@subplotlayoutInvalid,p});
0554     handle.listener(handle(fig),'FigureUpdateEvent',{@subplotlayout,p})];
0555 for k=1:length(axlisth)
0556     ax = axlisth(k);
0557     if ~isappdata(double(ax),'SubplotDeleteListener')
0558         setappdata(double(ax),'SubplotDeleteListener',...
0559             handle.listener(ax,'ObjectBeingDestroyed', ...
0560             @axesDestroyed));
0561     end
0562 end
0563 setappdata(p,'SubplotListeners',list)
0564 
0565 % Add ax to a matrix of handles in the specified location.
0566 % The grid is stored on the parent appdata.
0567 % Also store the insets in ax appdata.
0568 % Only stores the axes if it is in a 1-by-1 cell and
0569 % the grid size matches any existing grid.
0570 function addAxesToGrid(ax,nrows,ncols,row,col,position)
0571 p = get(ax,'parent');
0572 grid = getappdata(p,'SubplotGrid');
0573 if isempty(grid)
0574     grid = zeros(nrows,ncols);
0575 end
0576 if any(size(grid) ~= [nrows ncols]), return; end
0577 if length(row) ~= 1 || length(col) ~= 1, return; end
0578 if round(row) ~= row || round(col) ~= col, return; end
0579 if grid(row+1,col+1) == ax, return, end
0580 grid(row+1,col+1) = ax;
0581 list = grid(:);
0582 list(list == 0) = []; % remove root
0583 list(~ishghandle(list)) = []; % remove invalid handles
0584 createListeners(p,handle(list));
0585 setappdata(p,'SubplotGrid',grid)
0586 setappdata(ax,'SubplotPosition',position); % normalized
0587 subplotlayoutInvalid(handle(ax),[],p);
0588 
0589 % Remove ax from grid of subplots in p
0590 function removeAxesFromGrid(p,ax)
0591 grid = getappdata(p,'SubplotGrid');
0592 if ~isempty(grid)
0593     n = grid == ax;
0594     if any(n(:))
0595         grid(n) = 0;
0596         list = grid(:);
0597         list(list == 0) = []; % remove root
0598         list(~ishghandle(list)) = [];
0599         if isempty(list)
0600             rmappdata(p,'SubplotListeners');
0601             rmappdata(p,'SubplotGrid');
0602         else
0603             setappdata(p,'SubplotGrid',grid);
0604         end
0605     end
0606 end
0607 
0608 % Callback when axis moves to remove it from subplot layout grid
0609 function axesMoved(hSrc,evdata) %#ok
0610 ax = double(evdata.affectedObject);
0611 % If the legend or colorbar is causing the move, do not remove the axes
0612 % from the subplot grid. Do, however, update it's cached position:
0613 if (isappdata(ax,'inLayout') && ~isempty(getappdata(ax,'inLayout'))) || ...
0614     isappdata(ax,'LegendColorbarReclaimSpace')
0615     setappdata(ax,'SubplotPosition',get(ax,'Position'));
0616 else
0617     removeAxesFromGrid(get(ax,'Parent'),ax);
0618 end
0619 
0620 % Callback when axis changes units
0621 function axesUnitsPreSet(hSrc,evdata) %#ok
0622 ax = double(evdata.affectedObject);
0623 p = get(ax,'Parent');
0624 list = getappdata(p,'SubplotListeners');
0625 if ~isempty(list)
0626     set(list(2:end),'enable','off');
0627 end
0628 
0629 % Callback when axis done changing units
0630 function axesUnitsPostSet(hSrc,evdata) %#ok
0631 ax = double(evdata.affectedObject);
0632 p = get(ax,'Parent');
0633 list = getappdata(p,'SubplotListeners');
0634 if ~isempty(list)
0635     set(list(2:end),'enable','on');
0636 end
0637 
0638 % Callback when axis destroyed
0639 function axesDestroyed(hSrc,evdata) %#ok
0640 ax = double(hSrc);
0641 p = get(ax,'Parent');
0642 if strcmp(get(p,'BeingDeleted'),'off')
0643     removeAxesFromGrid(p,ax);
0644 elseif isappdata(p,'SubplotListeners')
0645     rmappdata(p,'SubplotListeners');
0646     rmappdata(p,'SubplotGrid');
0647 end
0648 
0649 function str = id(str)
0650 str = ['MATLAB:subplot:' str];
0651 
0652 %----------------------------------------------------------------%
0653 % Convert units of offsets like LooseInset or TightInset
0654 % Note: Copied from legendcolorbarlayout.m
0655 function out = offsetsInUnits(ax,in,from,to)
0656 fig = ancestor(ax,'figure');
0657 par = get(ax,'Parent');
0658 p1 = hgconvertunits(fig,[0 0 in(1:2)],from,to,par);
0659 p2 = hgconvertunits(fig,[0 0 in(3:4)],from,to,par);
0660 out = [p1(3:4) p2(3:4)];
0661 
0662 %----------------------------------------------------------------%
0663 % Compute reference OuterPos from pos and loose. Note that
0664 % loose insets are relative to outerposition
0665 % Note: Copied from legendcolorbarlayout.m
0666 function outer = getOuterFromPosAndLoose(pos,loose,units)
0667 if strcmp(units,'normalized')
0668     % compute outer width and height and normalize loose to them
0669     w = pos(3)/(1-loose(1)-loose(3));
0670     h = pos(4)/(1-loose(2)-loose(4));
0671     loose = [w h w h].*loose;
0672 end
0673 outer = [pos(1:2)-loose(1:2) pos(3:4)+loose(1:2)+loose(3:4)];

Generated on Sun 14-Jun-2015 17:12:45 by m2html © 2005