Adding text annotation to figure programmatically - matlab

I would like to add text annotation to a figure from a GUI made with GUIDE. First I plot some data, than when the user clicks on a checkbox I call the text function in the event handler like this:
text(obj.XData(q), obj.YData(q)+10, int2str(q), 'Units', 'pixels');
obj is the line object itself, q is a counter for each point in the plot. It runs without errors, but nothing happens. I suppose I should 'refresh' the axis somehow, but refresh command doesn't help and I haven't found anything in the documentation.
Edit: I have found out that my code was wrong: pixel units correspond to a coordinate system where the origin is the lower-left corner of my axis control, what is not the same as my data coordinate system. I fixed this problem with ds2nfu, and when I paint before plotting everything is fine. But after plotting I see nothing. Is it possible that there is some kind of z-order problem with annotations?

As I mentioned in the comments, you should use the normalized units to place things in the same coordinate system as the data.
Now for the other problem. I'm not sure if this is a z-order issue, but if it is, you can bring the text to the front using UISTACK:
hText = text(x,y,'str');
uistack(hText, 'top')

Related

MATLAB Bar Graph Plotting Over Axes

I have a troubling problem that I've been trying to figure out for quite a while now and I just have no clue why it's happening. I have a self-coded GUI and I have a panel on the main GUI figure. On this panel I have an axes and whenever I plot a bar graph on that axes and try to edit its view with either yLim() or axis(), the axes will be resized to the dimensions I want, but the bar graph will not chop off at the edge of the axes and it will continue to run off the page. After playing around with it for a while in debug mode, I have found out that if I change the axes' parent from the panel it's on to the main figure, the bar graph will properly display only what is inside the axes borders like I want it to. I don't want to use changing the axes' parent as a permanent solution since I have several different panels I want to go between and having an axes on the main figure instead of the panel wouldn't work but I'd like to know if anybody knows why this is happening and how I can fix it.
For example, this code produces the problem I'm experiencing:
mainFig = figure('Units','characters',...
'Position',[40 5 200 50],...
'Color',[100/255 145/255 209/255]);
axesPanel = uipanel('bordertype','etchedin',...
'Parent',mainFig,...
'Title','Axes Panel');
mainAxes = axes('parent',axesPanel,...
'Units','characters');
bar(mainAxes,1:10,1:10)
ylim(mainAxes,[6 10])
And if the axes' parent is changed to be the figure, the problem doesn't exist. This line of code does that:
set(mainAxes,'parent',mainFig)
Thanks for any help or information as to why this is happening!
Just in case anybody else was having this same problem, I contacted MATLAB Technical Support and I was told that this was a bug on MATLAB's end that is being fixed in the next release(R2014b). They said that if you are having the problem I described in my original question, that in order to make the bar graph appear within the axes' boundaries at the moment, that you can edit the figure's 'Renderer' property and set it to either 'opengl' or 'zbuffer'. I have tested this and both options work so hopefully that helps :)
And just for extra clarification if it is needed, all I needed to change from my original code was:
mainFig = figure('Units','characters',...
'Position',[40 5 200 50],...
'Color',[100/255 145/255 209/255]);
To this:
mainFig = figure('Units','characters',...
'Renderer','opengl',...
'Position',[40 5 200 50],...
'Color',[100/255 145/255 209/255]);
And now the bar graph behaves as it should.

Matlab datatips: no text visible with view([0 90])

When I create a surface plot and use view([0 90]), so that I get a nice top-down view of the plot, the datatips are empty, i.e. the text is not visible. See the attached picture. As soon as I move the view a little bit they become visible though. Why is this happening and is there any fix?(1)
I don't really like the workaround to use view([0 90.0001]) instead. I'd rather see a fix than a workaround.
Mind that this doesn't happen when you save the file as a picture.
(1) It has probably something to do with heights. I think that the text height is at the exact same height as the box, which makes it possible that the text is drawn before the box, overwriting the text. I noticed that the box in that view sometimes disappears behind a surface which has a positive z-axis value.

How to prevent the fill command in MATLAB from creating boxes without "corners"

I am currently using the fill command in MATLAB to create a graph of boxes that were created using the 'fill' command (the actual code is based off this StackOverflow Question.
My issue is that the boxes that I create do not have "corners." I am attaching a PNG that illustrates the issue. Note that you have to look a little carefully since the image was heavily rendered, though in this example my arrows also look weird since they don't have edges either)
I am wondering if anyone has an idea of what might be going wrong? The boxes appear this way immediately after I use the fill command, which has the following structure:
fill(X,Y,MyFaceColor,'FaceAlpha',0.5,'EdgeColor', MyEdgeColor,'LineStyle','','LineWidth',box_line_width,'EdgeAlpha',1)
The function fill appears to leave space for corner markers if they are not explicitly defined. Hence, calling fill with the marker property will solve your problem. However, since markers and linewidths seem to work on different scales, you will have to play around with the marker size to get smooth edges.
Example:
fill(X,Y,'r','FaceAlpha',0.5,'EdgeColor', 'k',...
'LineWidth', 5,'EdgeAlpha',1 , 'marker', '.', 'markersize', 15)

Matlab rotate3D and buttondownfcn incompatibility

Hi everyone and thanks in advance for all your help.
I'm currently working on a UI in matlab that includes 4 differents axes to show various info. Basicly, I have MRI data (so 3D data) that I want to show. I use 1 axe to show 3 perpendicular plane that split the data at its center (axeMain), and 3 other axes that shows the planes individually (axeX,axeY and axeZ). I have a main axe on wich I want to make rotations possible (only on the main axis system) and I want to be able to select coordinate on the 3 other axe (those with 1 plane only). I also unable translations but that is out of scope for my problem.
So basicly, I have no problem selecting my coordinates (using the buttondownfcn on my planes) on all of the 3 axes and I also have no problem using rotate3D on the mainAxe. HOWEVER, if I try to have both to work at the same time, the buttondownfcn doesn't work anymore. I don't understand why it's doing this (I have some ideas but that's about it) and I have no idea how to work around it. Basicly my code for those functions are like this :
rotate3d(handles.axisMain);
%some other code, setting up other UI stuff
%allow selection on the 3 static plains.
set([handles.axeX,handles.axeY,handles.axeZ], 'buttondownfcn', #getCoord);
So my question is basicly : why wont those 2 functions don't work together and how to work around that problem, ideally with minimal code change?
Thanks.
EDIT : this is a print screen of my current interface. I want to be able to select coordinate using ONLY on the 3 last axes (containing only 1 plane in each of them). I also want to be able to rotate images ONLY on the first axe (the one with 3 planes). Hope this clarify.
I would also like to note this : following my tests, I found that the mouse click would not raise at all if the rotate3D is activated. The problem is not in the logic I use to get the coordinates itself, but in the click event not being fired.
Also, I am aware that the event is not on the surface that I try to print. The actual code is like this :
set(h, 'buttondownfcn', #getCoord);
set(h,'HitTest','on');
where h is the handle of a surface and each surfaces are processed this way.
I have found the exact solution!
Exploring the code for rotate3d(hAxe,'on') , i have found that they key line is getuimode(hFig,'Exploration.Rotate3d') wich returns uitools.uimode that contains ButtonDownFilter and ModeStateData methods.
Finally i have solved the problem in the following way:
rotate3d(hAxe,'on')
uiMode = getuimode(hFig,'Exploration.Rotate3d');
uiMode.ButtonDownFilter = #mycallback;
where:
hAxe is the handle to the axes object
hFig is the handle to the figure object
#mycallback is the callback that lets buttondownfcn and rotate3d works together as in the example of Matlab's help
So, you have to tag the object that you want to not be ignored:
set(hAxe,'tag','DoNotIgnore')
And write the callback:
function [flag] = mycallback(obj,event_obj)
% If the tag of the object is 'DoNotIgnore', then return true
objTag = obj.Tag;
if strcmpi(objTag,'DoNotIgnore')
flag = true;
else
flag = false;
end
maybe
set(handles.axisMain, 'buttondownfcn', #getCoord);

MATLAB: impoint getPosition strange behaviour

I have a question about the values returned by getPosition. Below is my code. It lets the user set 10 points on a given image:
figure ,imshow(im);
colorArray=['y','m','c','r','g','b','w','k','y','m','c'];
pointArray = cell(1,10);
% Construct boundary constraint function
fcn = makeConstrainToRectFcn('impoint',get(gca,'XLim'),get(gca,'YLim'));
for i = 1:10
p = impoint(gca);
% Enforce boundary constraint function using setPositionConstraintFcn
setPositionConstraintFcn(p,fcn);
setColor(p,colorArray(1,i));
pointArray{i}=p;
getPosition(p)
end
When I start to set points on the image I get results like [675.000 538.000], which means that the x part of the coordinate is 675 and the y part is 538, right? This is what the MATLAB documentation says, but since the image is 576*120 (as displayed in the window) this is not logical.
It seemed to me like, somehow, getPosition returns the y coordinate first. I need some clarification on this.
Thanks for help
I just tried running your code in MATLAB 7.8.0 (R2009a) and had no problems with image sizes of either 576-by-120 or 120-by-576 (I was unsure which orientation you were using). If I left click inside the image, it places a new movable point. It did not allow me to place any points outside the image.
One small bug I found was that if you left-click in the image, then drag the mouse pointer outside the image while still holding the left button down, it will place the movable point outside the image and won't display it, displaying a set of coordinates that are not clipped to the axes rectangle.
I'm not sure of what could be your problem. Perhaps it's a bug with whatever MATLAB version you are using. I would suggest either restarting MATLAB, or clearing all variables from the workspace (except for the image data im).
Might be worth checking to see which renderer you are using (Painter or OpenGL), a colleague showed me some wierd behaviour with point picking when using the OpenGL renderer which went away when using the Painter renderer.
Your code uses the Image Processing Toolbox, which I don't have, so this is speculation. The coordinate system is probably set to the figure window (or maybe even the screen), not the image.
To test this, try clicking points outside the image to see if you can find the origin.