How to display slope on a plot in Matlab - matlab

I used the regress function to find the slope for some data I plotted. I have managed to plot the data and the fitted line both on the same plot. I know how to make it clear that the fitted line is the slope, but I would also like to add a box in corner of the graph (dont care where) that shows the actual value of the slope (basically shows the value that the regress function returns), and I'm trying to find a way to do this automatically (like if there's a function for that or something). Can anybody help (I hope I explained my question well enough...)?

I didn't try to recreate your slope line but have you considered using an annotation?
Example:
x = [-1:.2:1];
plot(x,x.^2,'-bo');
annotation('textbox', [.4 .4 .1 .1], 'String', ...
['slope at x = 0.6 is: ',num2str(2*.6)]);
Which shows:
Of course you can control how the box is positioned, formatted, and so forth.
Check the help files for more detailed info. In some cases you might also consider using a legend().

The function text adds text to a figure. It requires a position and a string to display. In addition, you can highly customize the appearance of the text. For example:
x = 1:100;
y = randn(size(x)) + 0.3*x;
plot(x,y,'.');
p = polyfit(x,y,1);
hold on;
plot(x, polyval(p,x),'k-');
h = text(min(xlim(gca)), max(ylim(gca)), ...
sprintf('%fx + %f', p(1), p(2)),...
'verticalalignment','top',...
'horizontalalignment','left');
Then, to see the various settinsg you can change, look at:
get(h)
Those properties can almost all be changes at creation (like verticalalignment above) or after creation (e.g. set(h, verticalalignment, 'top')).

Related

Indicate name of filled areas inside area plot - Matlab?

It's difficult to identify in this area plot each one of the many filled areas by just looking at the legend (it's like 16!).
So, I was wondering if there's a way to place some sort of labels (with a pointer perhaps?) inside the plot that clearly identifies each filled areas?
Thanks!
Here is an alternative using annotation objects and the textarrow option, which displays text along with an arrow. This could be useful to you to point in narrow regions where text would hide data.
For example:
clear
clc
close all
x = 1:128;
%// Plot data
figure
hAxes1 = axes('Position',[.1 .1 .6 .8]);
image(x.');
axis off
colormap(jet(128))
%// Define labels
ColorLabels = {'Red';'Orange';'Green';'Blue';'More blue'};
%// Define starting and ending x and y positions
xstart = .8;
xend = .6;
ystart = linspace(.1,.8,numel(ColorLabels));
yend = linspace(.15,.8,numel(ColorLabels));
for k = 1:numel(ColorLabels)
annotation('textarrow', [xstart xend],[ystart(k) yend(k)],...
'String', ColorLabels{k});
end
gives the following output:
There may be a builtin way that I don't know about but I find the lower-level text function is usually the best answer for this kind of thing.
It'll require some housekeeping - you have to supply an x and y coordinate and the text to print, e.g.
text(20, 400, 'Region 4')
which will centre the label on (20,400) (see the 'VerticalAlignment' and 'HorizontalAlignment' name-value pairs in the docs for fine-tuning), so for me it's usually preferable to write a small wrapper that will work them out from the data. Of course this is usually specific to the particular type of data you're using and rarely generalises to other uses of area plots, but that's most likely why there isn't already a generic labelling function (that I'm aware of).

How to change font size of right axis of Pareto plot in Matlab

I am trying to bold the right side y axis for a Pareto plot in Matlab, but I can not get it to work. Does anyone have any suggestions? When I try to change the second dimension of ax, I get an error:
"Index exceeds matrix dimensions.
Error in pcaCluster (line 66)
set(ax(2),'Linewidth',2.0);"
figure()
ax=gca();
h1=pareto(ax,explained,X);
xlabel('Principal Component','fontweight','b','fontsize',20)
ylabel('Variance Explained (%)','fontweight','b','fontsize',20)
set(ax(1),'Linewidth',2.0);
set(ax(1),'fontsize',18,'fontweight','b');
%set(ax(2),'Linewidth',2.0);
%set(ax(2),'fontsize',18,'fontweight','b');
set(h1,'LineWidth',2)
Actually you need to add an output argument during the call to pareto and you will then get 2 handles (the line and the bar series) as well as 2 axes. You want to get the YTickLabel property of the 2nd axes obtained. So I suspect that in your call to pareto above you do not need to supply the ax argument.
Example:
[handlesPareto, axesPareto] = pareto(explained,X);
Now if you use this command:
RightYLabels = get(axesPareto(2),'YTickLabel')
you get the following (or something similar):
RightYLabels =
'0%'
'14%'
'29%'
'43%'
'58%'
'72%'
'87%'
'100%'
What you can do is actually to erase them altogether and replace them with text annotations, which you can customize as you like. See here for a nice demonstration.
Applied to your problem (with dummy values from the function docs), here is what you can do:
clear
clc
close all
y = [90,75,30,60,5,40,40,5];
figure
[hPareto, axesPareto] = pareto(y);
%// Get the poisition of YTicks and the YTickLabels of the right y-axis.
yticks = get(axesPareto(2),'YTick')
RightYLabels = cellstr(get(axesPareto(2),'YTickLabel'))
%// You need the xlim, i.e. the x limits of the axes. YTicklabels are displayed at the end of the axis.
xl = xlim;
%// Remove current YTickLabels to replace them.
set(axesPareto(2),'YTickLabel',[])
%// Add new labels, in bold font.
for k = 1:numel(RightYLabels)
BoldLabels(k) = text(xl(2)+.1,yticks(k),RightYLabels(k),'FontWeight','bold','FontSize',18);
end
xlabel('Principal Component','fontweight','b','fontsize',20)
ylabel('Variance Explained (%)','fontweight','b','fontsize',20)
which gives this:
You can of course customize everything you want like this.
That is because ax is a handle to the (first/left) axes object. It is a single value and with ax(1) you got lucky, its ax again, but ax(2) is simply not valid.
I suggest to read the docs about how to get the second axis. Another good idea always is to open the plot in the plot browser, click whatever object you want so it is selected and then get its handle by typing gco (get current object) in the command window. You can then use it with set(gco, ...).

How to specify the axis size when plotting figures in Matlab?

Suppose that I have 2 figures in MATLAB both of which plot data of size (512x512), however one figure is being plotted by an external program which is sets the axis parameters. The other is being plotted by me (using imagesc). Currently the figures, or rather, the axes are different sizes and my question is, how do I make them equal?.
The reason for my question, is that I would like to export them to pdf format for inclusion in a latex document, and I would like to have them be the same size without further processing.
Thanks in Advance, N
Edit: link to figures
figure 1: (big)
link to smaller figure (i.e. the one whose properties I would like to copy and apply to figure 1)
For this purpose use linkaxes():
% Load some data included with MATLAB
load clown
% Plot a histogram in the first subplot
figure
ax(1) = subplot(211);
hist(X(:),100)
% Create second subplot
ax(2) = subplot(212);
Now link the axes of the two subplots:
linkaxes(ax)
By plotting on the second subplot, the first one will adapt
imagesc(X)
First, you have the following:
Then:
Extending the example to images only:
load clown
figure
imagesc(X)
h(1) = gca;
I = imread('eight.tif');
figure
imagesc(I)
h(2) = gca;
Note that the configurations of the the first handle prevail:
linkaxes(h)
1.Get the handle of your figure and the axes, like this:
%perhaps the easiest way, if you have just this one figure:
myFigHandle=gcf;
myAxHandle=gca;
%if not possible, you have to search for the handles:
myFigHandle=findobj('PropertyName',PropertyValue,...)
%you have to know some property to identify it of course...
%same for the axes!
2.Set the properties, like this:
%set units to pixels (or whatever you prefer to make it easier to compare to the other plot)
set(myFigHandle, 'Units','pixels')
set(myAxHandle, 'Units','pixels')
%set the size:
set(myFigHandle,'Position',[x_0 y_0 width height]) %coordinates on screen!
%set the size of the axes:
set(myAxHandle,'Position',[x_0 y_0 width height]) %coordinates within the figure!
Ok, based on the answer of #Lucius Domitius Ahenoba here is what I came up with:
hgload('fig1.fig'); % figure whose axis properties I would like to copy
hgload('fig2.fig');
figHandles = get(0,'Children');
figHandles = sort(figHandles,1);
ax(1) = findobj(figHandles(1),'type','axes','-not','Tag','legend','-not','Tag','Colorbar');
ax(2) = findobj(figHandles(2),'type','axes','-not','Tag','legend','-not','Tag','Colorbar');
screen_pos1 = get(figHandles(1),'Position');
axis_pos1 = get(ax(1),'Position');
set(figHandles(2),'Position',screen_pos1);
set(ax(2),'Position',axis_pos1);
This is the 'before' result:
and this is the 'after' result:
Almost correct, except that the aspect ratios are still off. Does anybody know how to equalize everything related to the axes? (I realize that I'm not supposed to ask questions when posting answers, however adding the above as a comment was proving a little unwieldy!)

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

How to plot arrow with data coordinates in Matlab?

I know there is a function named annotation can plot arrows or double arrows. But annotation can only plot in normalized unit. For example:
annotation('arrows',[x1 x2],[y1 y2])
Here, [x1, x2] should be a ratio number less than one.
So, my question is how can I plot arrows with a true value rather than a normalized value?
I wonder if there is any other function can approach this or is there any function I can get the axis value of the figure so that I can adjust the true value into a normalized value.
For the positioning of annotations, Matlab offers the function dsxy2figxy to convert data space points to normalized space coordinates. However, for whatever reasons, the function is not included in the Matlab distribution and has to be "created" first.
Copy the following line into the command window and execute it to open the function in your editor.
edit(fullfile(docroot,'techdoc','creating_plots','examples','dsxy2figxy.m'))
To use the function dsxy2figxy save it somewhere in your matlab search path.
Please find the full instructions for the function dsxy2figxy at matlab-central: http://www.mathworks.de/help/techdoc/creating_plots/bquk5ia-1.html
Even though annotation uses normalized as default units, you can associate these objects to the current axes (gca) and use data units for setting X and Y properties.
Here is an example of plotting a single arrow.
plot(1:10);
ha = annotation('arrow'); % store the arrow information in ha
ha.Parent = gca; % associate the arrow the the current axes
ha.X = [5.5 5.5]; % the location in data units
ha.Y = [2 8];
ha.LineWidth = 3; % make the arrow bolder for the picture
ha.HeadWidth = 30;
ha.HeadLength = 30;
For anyone who comes across this topic looking to draw arrows in "data space" rather than in units relative to the figure and/or axes, I highly recommend arrow.m from the file exchange.
I've just discovered this method, since I don't want to have to bother with normalised units. Use the latex interpreter:
figure
plot([1:5],[1:5]*3,'.-')
%// Say I want to put an arrow pointing to the location, [3 9]
text(2.94,8.3,'\uparrow','fontsize',20)
text(2.8,7.8,'point [3,9]')
To make the arrow longer, use a larger fontsize.
Pros
Easier, faster and quicker than using normalised units
Don't need to install any functions (good for us lazy people..)
making use of the LaTeX interpreter, there is a whole range of arrows (up, down, left, right and other angles (see Symbol list)
Cons
Definitely needs trial and error/tweaking to get the correct location of the arrow head relative to the POI.
There is limited control over the length of the arrow
Some latex commands aren't understood by the interpreter (boo).
If I remember correctly you need to calculate the position of the axes in relation to the figure.
it should go like:
%% example plot
clf
plot(rand(5,2)*5)
%% get info specific to the axes you plan to plot into
set(gcf,'Units','normalized')
set(gca,'Units','normalized')
ax = axis;
ap = get(gca,'Position')
%% annotation from 1,2 to 3,4
xo = [1,3];
yo = [2,4];
xp = (xo-ax(1))/(ax(2)-ax(1))*ap(3)+ap(1);
yp = (yo-ax(3))/(ax(4)-ax(3))*ap(4)+ap(2);
ah=annotation('arrow',xp,yp,'Color','r');
Note Fixed offset in original calculation - ap(3),ap(4) are width and height of gca, not corner positions
After creating the annotation object you should set the property Units to an absolute one. Example:
arrowObj = annotation('arrow', [0.1 0.1], [0.5 0.5]);
set(arrowObj, 'Units', 'centimeters');
set(arrowObj, 'Position', [1 1 3 5]);
One approach would be to define an arrowhead in the axis units:
Ax=[0 -0.003 0.003 0]; % (Ax,Ay) form an upward pointing arrowhead.
Ay=[0.01 0.0060 0.0060 0.01];
Ax=Ax-mean(Ax); % center it on zero
Ay=Ay-mean(Ay);
Then at desired arrowhead index in on a curve vv, compute
x1=vv(in,1); y1=vv(in,2);
x2=vv(in+1,1); y2=vv(in+1,2);
u=x2-x1;
v=y2-y1;
th=-pi/2+atan2(v,u);
R=[cos(th) -sin(th); sin(th) cos(th)]; % Rotation matrix for local slope of vv.
A=R*[Ax;Ay]; % Rotate the arrowhead.
patch(x1+A(1,:),y1+A(2,:),'r','LineWidth',0.01) % plot rotated arrowhead at (x1,y1).
plot(x1+A(1,:),y1+A(2,:),'r','LineWidth',0.01) % Kludge to make boundary red too (I'm sure there is a more elegant way).
Worked for me, for my particular circumstances.
You can use the 'arrow' component in the (well-documented) DaVinci Draw toolbox (full disclosure: I wrote/sell the toolbox, though arrows are free).
Example syntax and example output are below.
davinci( 'arrow', 'X', [0 10], 'Y', [0 2], <plus-lots-of-options> )