annotation() and text() in Matlab - matlab

I wonder what is the difference between annotation() and text() functions in Matlab? In what cases are one of them preferred over the other?

TEXT positions text in relation to axes. In contrast, ANNOTATION position is figure-related. ANNOTATION can put on figure not only text, but lines, shapes, arrows, etc.
Consequently, TEXT takes axes handles as an argument (or gca for current axes), and ANNOTATION takes figure handles (or gcf for current figure).

Also, notice that they create different objects with different properties.
So for example, while TEXT objects can be rotated with the ROTATION property, ANNOTATION objects lack this property and cannot be rotated.

Related

Controlling the color of text in an array based on a predefined condition

I am trying to display a matrix M of size 50x8 with a plot using text([x,y],M). All the entries in matrix are at present of the same color. I would like more control on the display, and would like that all matrix entries satisfying a particular condition should be of different color.
One of the possible ways to do is to specify the position for each of the elements of the matrix M individually in text(x,y,M_ij). But I am only specifying the position for the first element, and other positions are being assigned automatically. How can I get those positions, or control them? This will allow me to control the colors as well.
The resulting text graphics object is only one object, so you can't adjust the color through handle graphics without affecting all of the rows. But if it's possible for you, you can specify the color directly in the strings. To do this, you'll probably need to represent your strings as a cell array instead, so they can have different colors.
M = {'\color{red}Line 1';'\color{blue}Line 2';'\color[rgb]{.6 .8 .2}Line 3'};
text(1, 1, M);
The reference for other inline string markup is found on this doc page, in the 'String' property: http://www.mathworks.com/help/matlab/ref/text_props.html

Determine/Save the position of text in matlab

I plotted few points using scatter and then label them using text. The position of these labels are same as the position of the points + some offset. Some of these text label overlap with each other and hence I moved them interactively (using mouse). I can check the new position of each of these text individually using property editor. However this is very time-consuming. Is there a better way to get the coordinates of all these text-label?
You can use findobj to get handles to text objects that are children of the current axes (or another handle... your choice):
text_handles = findobj('parent',gca,'type','text');
Then you can get the positions of these text objects:
positions = get(text_handles,'position');
You may need to do a bit more work to associate each text object with its data point - I suggest taking advantage of the property system, perhaps via the UserData field, for this, though there are many options.
If you want to do it easily later do this in your plots, for example:
h=text(2.9,7.5,'MyText');
This will put "MyText" at position 2.9, and 7.5.
Then to change the position use:
set(h,'Position',[2.5 7]);
This will change the position to 2.5 and 7.
Later if you need to see tthe position of text again use:
get(h);
Hope this helps.

Using handles returned with findobj [duplicate]

I already have the functions required to drag and drop a single box in a figure in MATLAB. The code I wrote fills the figure with several boxes. With another loop I filled the figure with more boxes (which hold different information in string form).
These two sets of boxes are related by the numbers I placed in their UserData (corresponding numbers; for each box, there's another with the same UserData content). By finding boxes containing the same UserData (and thus relating them) I want to be able to relocate a member of the first set of boxes to the same position relative to the corresponding member of the second set of boxes, by means of right clicking on the box I just dragged (uicontextmenu).
function recallfcn(hObject,eventdata)
for ydx=1:2
diag_detail=get(gco,'UserData'); % This line should be in the drag fcn
diag_pos=get(gco,'Position'); % So should this one (for current objects)
xvar=diag_pos(1,1);
yvar=diag_pos(1,2);
detail=[diag_detail ydx];
set(findobj('UserData',detail),'Position',[xvar+(ydx-1.5) yvar+0.5 0.8 0.8]);
end
end
% ydx is only there to add another level of detail as I'm actually looking to move
% two boxes of the 'first kind', each of which have 2 numbers in user data, the first
% number being the same, and the second number distinguishing the first box from the
% second. The premise is the same.
I usually use findall instead of findobj, in case the handles of the objects are not visible from the outside. Other than that I don't see why your code wouldn't work.
Here's an example:
%# make a figure with two buttons, same userData
fh=figure,
uicontrol('userdata',[2 3],'parent',fh)
uicontrol('userData',[2 3],'units','normalized','position',[0.5 0.5,0.1 0.1],'parent',fh)
%# change color to red
set(findall(fh,'userData',[2 3]),'backgroundcolor','r')
%# move to the same position
set(findall(fh,'userData',[2 3]),'position',[0.3,0.3,0.1,0.1])
As Jonas alludes to, the 'HandleVisibility' property of an object will determine if the object shows up in its parent's list of children, and thus if it will be returned by functions like FINDOBJ. The standard fix is to use the function FINDALL instead.
However, the 'HandleVisibility' property also comes into play in determining whether or not an object can become the current object (i.e. returnable by the function GCO). If it is set to 'off', then that object can't become the current object. Additionally, if the 'HandleVisibility' property of the parent figure of an object is set to 'off' then none of its children (including said object) can become the current object.
If 'HandleVisibility' is set to 'on' or 'callback' for all your objects and figures, then I think everything should work fine.
you should inverse the ordre of x and y vector, and you can use just one loop, the changment in your code is :
x2=x(end:-1:1); % invers the ordre
y2=y(end:-1:1);
for i=1:length(x)
set(hLine,'xdata',x(i),'ydata',y(i)); % move the point using set
% to change the cooridinates.
set(hLine2,'xdata',x2(i),'ydata',y2(i));
M(i)=getframe(gcf);
end

Moving multiple boxes in figure?

I already have the functions required to drag and drop a single box in a figure in MATLAB. The code I wrote fills the figure with several boxes. With another loop I filled the figure with more boxes (which hold different information in string form).
These two sets of boxes are related by the numbers I placed in their UserData (corresponding numbers; for each box, there's another with the same UserData content). By finding boxes containing the same UserData (and thus relating them) I want to be able to relocate a member of the first set of boxes to the same position relative to the corresponding member of the second set of boxes, by means of right clicking on the box I just dragged (uicontextmenu).
function recallfcn(hObject,eventdata)
for ydx=1:2
diag_detail=get(gco,'UserData'); % This line should be in the drag fcn
diag_pos=get(gco,'Position'); % So should this one (for current objects)
xvar=diag_pos(1,1);
yvar=diag_pos(1,2);
detail=[diag_detail ydx];
set(findobj('UserData',detail),'Position',[xvar+(ydx-1.5) yvar+0.5 0.8 0.8]);
end
end
% ydx is only there to add another level of detail as I'm actually looking to move
% two boxes of the 'first kind', each of which have 2 numbers in user data, the first
% number being the same, and the second number distinguishing the first box from the
% second. The premise is the same.
I usually use findall instead of findobj, in case the handles of the objects are not visible from the outside. Other than that I don't see why your code wouldn't work.
Here's an example:
%# make a figure with two buttons, same userData
fh=figure,
uicontrol('userdata',[2 3],'parent',fh)
uicontrol('userData',[2 3],'units','normalized','position',[0.5 0.5,0.1 0.1],'parent',fh)
%# change color to red
set(findall(fh,'userData',[2 3]),'backgroundcolor','r')
%# move to the same position
set(findall(fh,'userData',[2 3]),'position',[0.3,0.3,0.1,0.1])
As Jonas alludes to, the 'HandleVisibility' property of an object will determine if the object shows up in its parent's list of children, and thus if it will be returned by functions like FINDOBJ. The standard fix is to use the function FINDALL instead.
However, the 'HandleVisibility' property also comes into play in determining whether or not an object can become the current object (i.e. returnable by the function GCO). If it is set to 'off', then that object can't become the current object. Additionally, if the 'HandleVisibility' property of the parent figure of an object is set to 'off' then none of its children (including said object) can become the current object.
If 'HandleVisibility' is set to 'on' or 'callback' for all your objects and figures, then I think everything should work fine.
you should inverse the ordre of x and y vector, and you can use just one loop, the changment in your code is :
x2=x(end:-1:1); % invers the ordre
y2=y(end:-1:1);
for i=1:length(x)
set(hLine,'xdata',x(i),'ydata',y(i)); % move the point using set
% to change the cooridinates.
set(hLine2,'xdata',x2(i),'ydata',y2(i));
M(i)=getframe(gcf);
end

Does Matlab execute a callback when a plot is zoomed/resized/redrawn?

In Matlab, I would like to update the data plotted in a set of axes when the user zooms into the plot window. For example, suppose I want to plot a particular function that is defined analytically. I would like to update the plot window with additional data when the user zooms into the traces, so that they can examine the function with arbitrary resolution.
Does Matlab provide hooks to update the data when the view changes? (Or simply when it is redrawn?)
While I have yet to find one generic "redraw" callback to solve this question, I have managed to cobble together a group of four callbacks* that seem to achieve this goal in (almost?) all situations. For a given axes object ax = gca(),
1. Setup the zoom callback function as directed by #Jonas:
set(zoom(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
2. Setup a pan callback function:
set(pan(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
3. Setup a figure resize callback function:
set(getParentFigure(ax),'ResizeFcn',#(x,y) myCallbackFcn(ax));
4. Edit: this one no longer works in R2014b, but is only needed if you add, e.g., a colorbar to the figure (which changes the axis position without changing the figure size or axis zoom/pan). I've not looked for a replacement. Finally, setup an undocumented property listener for the axes position property itself. There is one important trick here: We must hold onto the handle to the handle.listener object as once it's deleted (or leaves scope), it removes the callback. The UserData property of the axes object itself is a nice place to stash it in many cases.
hax = handle(ax);
hprop = findprop(hax,'Position');
h = handle.listener(hax,hprop,'PropertyPostSet',#(x,y) myCallbackFcn(ax));
set(ax,'UserData',h);
In all these cases I've chosen to discard the default callback event arguments and instead capture the axis in question within an anonymous function. I've found this to be much more useful than trying to cope with all the different forms of arguments that propagate through these disparate callback scenarios.
*Also, with so many different callback sources flying around, I find it invaluable to have a recursion check at the beginning of myCallbackFcn to ensure that I don't end up in an infinite loop.
Yes, it does. The ZOOM mode object has the following callbacks:
ButtonDownFilter
ActionPreCallback
ActionPostCallback
The latter two are executed either just before or just after the zoom function. You could set your update function in ActionPostCallback, where you'd update the plot according to the new axes limits (the handle to the axes is passed as the second input argument to the callback).