Get multiple axes handles at once - matlab

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');

Related

multiple eyediagrams on a single figure in MATLAB

Is there a way to have multiple eyediagrams on a single figure in MATLAB. I want to do something like this:
figure;
subplot(311);
eyediagram(x1, ....);
subplot(312);<br>
eyediagram(x2, ....);
subplot(313);
eyediagram(x3, ....);
Unfortunately each call to eyediagram creates its own plot. I already tried to plot multiple eyediagram and copy them individually to another figure but I was wondering if there is a better/cleaner way to do this.
Thanks!
From the documentation:
Note: You cannot use hold on to plot multiple signals in the same figure.
Based on that statement, and the fact that you can only specify a figure handle to eyediagram (see below) and not an axes handle, this is not possible apart from manually copying the plot objects as you have stated (likely using copyobj).
Specifying a Figure
eyediagram(x,n,period,offset,plotstring,h) is the same as the syntax above, except that the eye diagram is in the figure whose handle is h, rather than in a new figure. h must be a handle to a figure that eyediagram previously generated.

Suppress function display in matlab ezpolar

I am using ezpolar to draw an arc on a compass plot. It's super easy,
ezpolar('1', [TH1, TH2])
to plot a circular arc with a radius 1 over the range [TH1, TH2]. However the function itself "r=1" gets displayed on the plot, which I do not want. I can't find and references to how this can be suppressed with an extra parameter or something.
I realise I could plot the arc other ways, but this is a cool function and super-compact, so I'd like to use it here and in the future.
Anyone know how to suppress the displaying of the function on the plot?
Thanks in advance
Tricky!
It looks like ezpolar is one of those MATLAB plots where a lot of things happen but nothing gets returned to the user. However I found the way using findobj.
Fiddling with the plot I realized that it is a 'Text' object what MATLAB puts in the plot, so we can try to find it with
h = findobj(gca,'Type','Text')
and then delete the text, for example with:
h.String='';
Tada!

Matlab - How to make a figure current? How to make an axes current?

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');

Matlab: How to obtain all the axes handles in a figure handle?

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).

Plotting multi-colored line in Matlab

I would like to plot a vertical line (I'd prefer any orientation, but I'd be happy with just vertical right now) with two-color dashes, say red-blue-red-blue-...
I know I could do it like this:
plot([1,1],[0,1],'r'),
hold on,
plot([1,1],[0,1],'--b')
However, since I need to be able to move the line, among others, it should only have a single handle. How could I do this?
EDIT
Thank you for your answers. I guess I should indeed give some more information.
I have some data that is classified into different parts. I want to be able to manually adjust the boundaries between classes. For this, I'm drawing vertical lines at the classification boundaries and use draggable to allow moving the lines.
For the boundary between the red and the blue class, I'd like to have a red/blue line.
plot(ones(10,1),linspace(0,1,10),'-bs','MarkerFaceColor','r','MarkerEdgeColor','none','linewidth',6)
is what I'm actually using at the moment. However, it's not so pretty (if I want equal spacing, it becomes a real pain, and I want to give both colors the same weight), and I would like to have the possibility to use three colors (and not with marker edge and face being different, because it makes my eyes bleed).
Unfortunately, draggable does not allow me to use multiple handles, and grouping the lines with hggroup does not seem to create a draggable object.
cline looks like a promising approach, but rainbow colors won't work for my application.
You can use the code you have, and just concatenate the handles from each line into a vector of handles. When you want to change the properties of both lines simultaneously, the SET function is able to accept the vector of handles as an argument. From the documentation for SET:
set(H,'PropertyName',PropertyValue,...)
sets the named properties to the
specified values on the object(s)
identified by H. H can be a vector of
handles, in which case set sets the
properties' values for all the
objects.
Here's an example:
h1 = plot([1 1],[0 1],'r'); %# Plot line 1
hold on;
h2 = plot([1 1],[0 1],'--b'); %# Plot line 2
hVector = [h1 h2]; %# Vector of handles
set(hVector,'XData',[2 3]); %# Shifts the x data points for both lines
UPDATE: Since you mention you are using draggable from the MathWorks File Exchange, here's an alternate solution. From the description of draggable:
A function which is called when the
object is moved can be provided as an
optional argument, so that the
movement triggers further actions.
You could then try the following solution:
Plot your two lines, saving the handle for each (i.e. h1 and h2).
Put the handle for each in the 'UserData' property of the other:
set(h1,'UserData',h2);
set(h2,'UserData',h1);
Create the following function:
function motionFcn(hMoving) %# Currently moving handle is passed in
hOther = get(hMoving,'UserData'); %# Get the other plot handle
set(hOther,'XData',get(hMoving,'XData'),... %# Update the x data
'YData',get(hMoving,'YData')); %# Update the y data
end
Turn on draggable for both lines, using the above function as the one called when either object is moved:
draggable(h1,#motionFcn);
draggable(h2,#motionFcn);
I've never used it, but there's a submission by Sebastian Hölz called CLINE on the Mathworks File Exchange that seems related.
I don't know how to do exactly what you want, but presumably the reason you want to do this is to have some way of distinguishing this line from other lines. Along those lines, take a look at MathWorks' documentation on 2-D line plots. Specifically, this example:
plot(x,y,'--rs','LineWidth',2,...
'MarkerEdgeColor','k',...
'MarkerFaceColor','g',...
'MarkerSize',10)
should give you plenty of ideas for variation. If you really need the two-color dashes, it might help to specify why. That way, even if we can't answer the question, perhaps we can convince you that you don't really need the two-color dashes. Since you've already ruled out the over-lapping solution, I'm fairly certain there's no solution that answers all of your needs. I'm assuming the two-colorness is the most fluid of those needs.