Robochameleon  v1.0
isolate_axes.m
1 %ISOLATE_AXES Isolate the specified axes in a figure on their own
2 %
3 % Examples:
4 % fh = isolate_axes(ah)
5 % fh = isolate_axes(ah, vis)
6 %
7 % This function will create a new figure containing the axes/uipanels
8 % specified, and also their associated legends and colorbars. The objects
9 % specified must all be in the same figure, but they will generally only be
10 % a subset of the objects in the figure.
11 %
12 % IN:
13 % ah - An array of axes and uipanel handles, which must come from the
14 % same figure.
15 % vis - A boolean indicating whether the new figure should be visible.
16 % Default: false.
17 %
18 % OUT:
19 % fh - The handle of the created figure.
20 
21 % Copyright (C) Oliver Woodford 2011-2013
22 
23 % Thank you to Rosella Blatt for reporting a bug to do with axes in GUIs
24 % 16/3/2012 Moved copyfig to its own function. Thanks to Bob Fratantonio
25 % for pointing out that the function is also used in export_fig.m.
26 % 12/12/12 - Add support for isolating uipanels. Thanks to michael for
27 % suggesting it.
28 % 08/10/13 - Bug fix to allchildren suggested by Will Grant (many thanks!).
29 % 05/12/13 - Bug fix to axes having different units. Thanks to Remington
30 % Reid for reporting the issue.
31 
32 function fh = isolate_axes(ah, vis)
33 % Make sure we have an array of handles
34 if ~all(ishandle(ah))
35  error('ah must be an array of handles');
36 end
37 % Check that the handles are all for axes or uipanels, and are all in the same figure
38 fh = ancestor(ah(1), 'figure');
39 nAx = numel(ah);
40 for a = 1:nAx
41  if ~ismember(get(ah(a), 'Type'), {'axes', 'uipanel'})
42  error('All handles must be axes or uipanel handles.');
43  end
44  if ~isequal(ancestor(ah(a), 'figure'), fh)
45  error('Axes must all come from the same figure.');
46  end
47 end
48 % Tag the objects so we can find them in the copy
49 old_tag = get(ah, 'Tag');
50 if nAx == 1
51  old_tag = {old_tag};
52 end
53 set(ah, 'Tag', 'ObjectToCopy');
54 % Create a new figure exactly the same as the old one
55 fh = copyfig(fh); %copyobj(fh, 0);
56 if nargin < 2 || ~vis
57  set(fh, 'Visible', 'off');
58 end
59 % Reset the object tags
60 for a = 1:nAx
61  set(ah(a), 'Tag', old_tag{a});
62 end
63 % Find the objects to save
64 ah = findall(fh, 'Tag', 'ObjectToCopy');
65 if numel(ah) ~= nAx
66  close(fh);
67  error('Incorrect number of objects found.');
68 end
69 % Set the axes tags to what they should be
70 for a = 1:nAx
71  set(ah(a), 'Tag', old_tag{a});
72 end
73 % Keep any legends and colorbars which overlap the subplots
74 lh = findall(fh, 'Type', 'axes', '-and', {'Tag', 'legend', '-or', 'Tag', 'Colorbar'});
75 nLeg = numel(lh);
76 if nLeg > 0
77  set([ah(:); lh(:)], 'Units', 'normalized');
78  ax_pos = get(ah, 'OuterPosition');
79  if nAx > 1
80  ax_pos = cell2mat(ax_pos(:));
81  end
82  ax_pos(:,3:4) = ax_pos(:,3:4) + ax_pos(:,1:2);
83  leg_pos = get(lh, 'OuterPosition');
84  if nLeg > 1;
85  leg_pos = cell2mat(leg_pos);
86  end
87  leg_pos(:,3:4) = leg_pos(:,3:4) + leg_pos(:,1:2);
88  ax_pos = shiftdim(ax_pos, -1);
89  % Overlap test
90  M = bsxfun(@lt, leg_pos(:,1), ax_pos(:,:,3)) & ...
91  bsxfun(@lt, leg_pos(:,2), ax_pos(:,:,4)) & ...
92  bsxfun(@gt, leg_pos(:,3), ax_pos(:,:,1)) & ...
93  bsxfun(@gt, leg_pos(:,4), ax_pos(:,:,2));
94  ah = [ah; lh(any(M, 2))];
95 end
96 % Get all the objects in the figure
97 axs = findall(fh);
98 % Delete everything except for the input objects and associated items
99 delete(axs(~ismember(axs, [ah; allchildren(ah); allancestors(ah)])));
100 return
101 
102 function ah = allchildren(ah)
103 ah = findall(ah);
104 if iscell(ah)
105  ah = cell2mat(ah);
106 end
107 ah = ah(:);
108 return
109 
110 function ph = allancestors(ah)
111 ph = [];
112 for a = 1:numel(ah)
113  h = get(ah(a), 'parent');
114  while h ~= 0
115  ph = [ph; h];
116  h = get(h, 'parent');
117  end
118 end
119 return