How do I obtain all the axes handles in a figure handle?
Given the figure handle hf, I found that get(hf, 'children') may return the handles of all axes. However, the Matlab Help suggests that it may return more than just the axes handles:
Children of the figure. A vector containing the handles of all axes, user-interface objects displayed within the figure. You can change the order of the handles and thereby change the stacking of the objects on the display.
Is there any way to obtain only the axes handle in the figure handle? Or how do I know if the handle returned by get(hf, 'children') is an axe handle?
Thanks!
Use FINDALL:
allAxesInFigure = findall(figureHandle,'type','axes');
If you want to get all axes handles anywhere in Matlab, you could do the following:
allAxes = findall(0,'type','axes');
EDIT
To answer the second part of your question: You can test for whether a list of handles are axes by getting the handles type property:
isAxes = strcmp('axes',get(listOfHandles,'type'));
isAxes will be true for every handle that is of type axes.
EDIT2
To select only axes handles that are not legends, you need to cleanup the list of axes (ax handles by removing all handles whose tag is not 'legend' or 'Colorbar':
axNoLegendsOrColorbars= ax(~ismember(get(ax,'Tag'),{'legend','Colobar'}))
Jonas' solution didn't work for me, because there were some handles referring to legends. Surprisingly, legends seem to be implemented as axes, at least in Matlab 2010a.
Here is a solution if you only want the axes, not any legends or other stuff.
axesHandles = get(fig, 'Children');
classHandles = handle(axesHandles);
count = length(axesHandles);
isNotInstanceOfSubtype = false(1, count);
for i = 1:count
isNotInstanceOfSubtype(i) = strcmp(class(classHandles(i)), 'axes') == 1;
end
axesHandles = axesHandles(isNotInstanceOfSubtype);
The script works by sorting out handles which reveal to be of a sub-type of type axes, for example scribe.legend.
A warning for those trying to improve the above code snippet: using something like
classHandles = cellfun(#(x) handle(x), axesHandles)
might not work as intended:
??? Error using ==> cellfun
scribe.legend type is not currently implemented.
"Jonas" and "tm1" have answers that work for some. However, as tm1 pointed the issue, there are several items inside type 'axes'.
To exactly refer to the legend or axes itself (there may exist other items), you need to differentiate them, using their characteristic properties.
In my example, I opened "property editor" and looked for differing properties for axes and legend (since they both belong to "type, axes"). I was trying to copy my axes and its legend:
copied_axes = findobj(temp_fig,'type','axes','Tag','');
copied_legend = findobj(temp_fig,'type','axes','Tag','legend');
Instead of 'Tag' property, I also could use an other property from the "Property Inspector". The thing is, they must differ. Most of their properties are the same.
The solution by #tm1 is excellent. Mine is a little less complicated (if you're ok with functional programming):
% initialize `fig` somehow, i.e., "fig=gcf()" for the current figure or
% "fig=get(0,'children')" for all open figures; can be vector or scalar.
ax = findall(fig, 'type', 'axes');
ax = ax(arrayfun(#(i) strcmp(class(handle(i)), 'axes'), ax));
ax will contain only plot axes. This works because the class of a legend or colorbar object is different from axes.
Edit #Jonas points out a potential improvement to filter the results of findall, because at least legends and colorbars seem to have non-empty Tag properties: replace the last line in the above code snippet with
ax = ax(strcmp('', get(ax, 'Tag')))
Both these techniques are kludgy and may break in the future (a comparison against ggplot2 or Bokeh might be interesting).
Related
I try to present 8 (name) labels on my x-axis. Instead, I get number 1 to 8.
Problem: In my previous asked question, I used gca function, that allows me to change axis labels. However, the same gca function doesn't work here.
This is my MatLab output:
Instead of 1,...8, I want to see Firm1...Firm8!
This is my code:
figure(2);
%four variables:
%pi --> 8x1 vector
%E_R_BL_Idzorek --> 8x1 vector
%pi_star1 --> 8x1 vector
%ER_100_TF1 --> 8x1 vector
ALL_DATA=[pi(1,1) E_R_BL_Idzorek(1,1) pi_star1(1,1) ER_100_TF1(1,1);pi(2,1) E_R_BL_Idzorek(2,1) pi_star1(2,1) ER_100_TF1(2,1);pi(3,1) E_R_BL_Idzorek(3,1) pi_star1(3,1) ER_100_TF1(3,1);pi(4,1) E_R_BL_Idzorek(4,1) pi_star1(4,1) ER_100_TF1(4,1);pi(5,1) E_R_BL_Idzorek(5,1) pi_star1(5,1) ER_100_TF1(5,1);pi(6,1) E_R_BL_Idzorek(6,1) pi_star1(6,1) ER_100_TF1(6,1);pi(7,1) E_R_BL_Idzorek(7,1) pi_star1(7,1) ER_100_TF1(7,1);pi(8,1) E_R_BL_Idzorek(8,1) pi_star1(8,1),ER_100_TF1(8,1)];
%plotting it with a bar function
bar(ALL_DATA);
%This is where I have problem with gca function
set(gca,'xticklabel',{'Firm1','Firm2','Firm3','Firm4','Firm5','Firm6','Firm7','Firm8'});
%this is the grid part:
grid on
ll = cell(1,4);
ll{1}='pi'; ll{2}='ERidz'; ll{3}='piTF'; ll{4}='ERTF';
legend(bar(ALL_DATA),ll);
You are using a newer version of MATLAB so you should use the newer graphics system. The newer system is based on objects. This makes setting properties of things like axes easier. For example:
fh = figure; % creates the figure window save the figure handle to set it's properties
ax = axes(fh); % creates the axes in the figure, again save the object
x = rand(8,100);
h = bar(ax, x); % create the bar graph in your axes object
% now use the saved object to access the exact feature you want. This way you always have the thing you want. No searching.
ax.XTickLabel = {'Firm1','Firm2','Firm3','Firm4','Firm5','Firm6','Firm7','Firm8'};
Saving the objects is also handy for tracking legends and other things. For example: legend(ax,... You know exactly which legend you're dealing with.
What appears to be happening is that you are correctly changing the XTicks as you want but then you overwrite your graph with legend(bar(.... That creates a new bar graph. Try changing that line to just legend(ll). I would still suggest using the object system.
It seems the problem is that you redraw the bar when you run
legend(bar(ALL_DATA),ll);
You should simply do
legend(ll);
I am looking for a one-liner to get multiple axes handles at once in an object array so that it can be passed into linkaxes. I am specifically looking for a single-line statement that does not use loops. I know I have done this in the past with a couple nested functions, but I can't figure out what I did.
The function gca can be used to get the axes handle for a specific figure, though this functionality does not appear to be documented. For example, call gca(3) to get the axis handle for Figure 3. I thought in the past I could call gca([1:4]) to get all four axes handles, but that does not seem to work.
I know that I can use get by calling get([1:4],'currentaxes'), which returns a cell array of axes handles. However, I have not figured out a way to convert a cell array of objects into an object array.
I'm using MATLAB R2015a.
Beside the answers already posted, a possible one-line solution could be:
linkaxes(findobj('type','axes'))
it also allows implicitly prevent considering figure without axes.
Hope this helps.
After building the axes:
figure(1); axes();
figure(2); axes();
figure(3); axes();
one-liners are fun:
linkaxes(arrayfun(#(k) get(k,'CurrentAxes'), 1:3));
Later Edit
Apparently this works only for old-style graphics (in which the handle of a graphic object is a double number). The new handle graphics (being proper objects) cannot be accumulated in a single array by arrayfun:
http://www.mathworks.com/help/matlab/graphics_transition/graphics-handles-are-now-objects-not-doubles.html
Maybe the much simpler one-liner:
linkaxes(findobj(1:3,'Type','Axes'));
would work...
How about this?
cell_of_axes = get([1:4], 'currentaxes');
array_of_axes = [cell_of_axes{:}];
linkaxes(array_of_axes);
If you only want to link a specific subset of axes and they are stored as objects in a cell:
linkaxes([all_axes{:}], 'x');
What's the field axes in the last line of the following code?
function drawBox2D(h,object)
% draw regular objects
if ~strcmp(object.type,'DontCare')
rectangle('Position',pos,'EdgeColor',occ_col{object.occlusion+1},...
'LineWidth',3,'LineStyle',trun_style{trc},'parent',h(1).axes)
rectangle('Position',pos,'EdgeColor','b', 'parent', h(1).axes)
See the h(1).axes in the last line? I don't know what is the h, don't know what to pass to that function.
I speculate it to be a graph handle. So I tried
h = figure(2);
drawBox2D(h, obj);
However the handle itself is an integer so there's no field called 'axes'.
Could anyone tell me who does the field axes belong to? And what should I pass as h into this function?
If you want to get all axes handles anywhere in Matlab, you can do the following things:
allAxes = findall(0,'type','axes');
To select only axes handles not legends, you need to cleanup the list of axes
axNoLegendsOrColorbars= ax(~ismember(get(ax,'Tag'),{'legend','Colobar'}));
If f is the figure handle, I wanted to use plot3(..) on it just like I would use plot(..), but this didn't work:
>> plot3(f, t, real(Y), imag(Y))
Error using plot3
Vectors must be the same lengths.
Then I figured out that the way to do this is to:
First make the relevant figure current.
Then use the plot3(..) function.
I can find what the current figure is using gcf, but how do I make a figure current (via its handle)?
This method has my personal preference:
set(0, 'currentfigure', f); %# for figures
set(f, 'currentaxes', axs); %# for axes with handle axs on figure f
because these commands are their own documentation. I find
figure(f)
and the like confusing on first read -- do you create a new figure? or merely make an existing one active? -> more reading of the context is required.
It is actually as simple as feeding the f back into the figure(..) command:
figure(f) %Makes the figure current.
Also, if I did something like this:
f = figure('IntegerHandle','off'); % With unique, non-reusable handle.
top = subplot(2, 1, 1);
bot = subplot(2, 1, 2);
Then I can make the axes top or bottom current by issuing a command like this:
subplot(top);
This also works:
axes(top);
But the two types of handles cannot be intermixed: axes(..) and subplot(..) work on axes handles, while figure(..) works on figure handles.
While others have provided you exactly what you've asked for (how to make an axes or figure the current one). My preferred way for dealing with this, is to explicitly specify the parent of your plot in the call to plot3.
If you look at the documentation, you will see that you can specify the parent axes as the first parameter to the function. If looks like you attempted to do this in your example, but you provided a handle to a figure rather than an axes.
f = figure()
ax = axes('Parent', f)
im = plot3(ax, X, Y, Z);
Alternately, I prefer the explicit solution
im = plot3(X, Y, Z, 'Parent', ax)
The nice thing about this explicit parameter/value specification of the parent is that it is accepted by all graphics objects. Functions like plot and plot3 are actually helper functions that wrap the functionality of line and allow for the convention of passing the parent first. The parameter/value approach is widely accepted regardless of whether you're working with a higher level function (plot, plot3, imshow) or the lower level objects (line, image, etc.)
The two benefits here are that you remove the overhead of MATLAB trying to figure out where to put your plot and also, it prevents MATLAB from having to change which figure is currently displayed, forcing a re-rendering which is one of MATLAB's slowest tasks.
give handle name to figure, give you a little example
f1 = figure;
imshow(image1);
f2 = figure;
imshow(image2);
% edit image 1
figure(f1);
text(2,3,'done');
I am writing two small psychoacoustic testing applications in MATLAB. The first one works without problems but the second one doesn't, and I just can't figure out why.
Here is the problem: the axes object is created, but it is empty.
failed_axis http://dl.getdropbox.com/u/98854/help.png
Here is the code that creates this figure and axes:
hFig = figure('dockcontrols','off','menubar','none', ...
'name','choose the better sounding file', ...
'numbertitle','off','position',[0,0,700,500], ...
'resize','off','toolbar','none','units','normalized', ...
'color',[.8,.8,.8]);
progress_idc = axes('position',[.1,.8,.8,.05],'box','on','parent',hFig,...
'xlim',[-.03,1.03],'xtickmode','manual','xtick',[], ...
'xticklabelmode','manual','xticklabel',[], ...
'ylim',[-1,1],'ytickmode','manual','ytick',[], ...
'yticklabelmode','manual','yticklabel',[], ...
'nextplot','add');
And here is the code that plots in this axes (the function is called regularly by a timer):
function replot(varargin) % this is a nested function
cla;
% plot start_indicator
plot([x_start,x_start],[-.7,.7],'k','linewidth',2);
fill([x_start,x_start-.02,x_start-.02],[0,-.7,.7],[0,0,0]);
% plot stop_indicator
plot([x_stop,x_stop],[-.7,.7],'k','linewidth',2);
fill([x_stop,x_stop+.02,x_stop+.02],[0,-.7,.7],[0,0,0]);
% plot play_position
plot([x_play,x_play],[-1,1],'r');
drawnow;
end
This is what it looks like if it works:
proper_axis http://dl.getdropbox.com/u/98854/help2.png
Do you have any idea what is going wrong here?
I ran the code you included above and got the correct output.
If I had to take a wild guess as to what the problem is, I'd guess that you may be creating other axes in your application that you are not listing above, or that you may have other axes not related to the application open at the time the application is running. When you plot your objects in the function replot, you are by default plotting them to the currently active axes. If you have multiple axes open, the plotting may therefore be going on in the wrong set of axes.
One suggestion I would make is to explicitly specify what the parent axes object should be in your calls to PLOT and FILL. If you add the arguments ...,'Parent',progress_idc); to your plotting calls, it will ensure that the correct axes is always used. I make a habit of always specifying the parent axes object instead of assuming that the currently active axes will always be the one I need it to be.
I finally found the (dumb) answer. The title accidentally had the same position as the plot axis. Due to some rendering-details of Matlab, it obscures the whole axis except for the rightmost and bottommost line of pixels, which makes the axis look "empty".
Oh, what a dumb error.