How to plot arrow with data coordinates in Matlab? - 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> )

Related

pzplots - Yticks and Colorbar Issue

I am using pzmap to plot system poles and zeros for different values of L. But the plot has additional YTick Labels at the right side which I cannot see in the axes properties. Also, I do not have the handle corresponding to constant damping gridlines whose color and properties I would like to change.
MWE
clear;clc
cb=parula(10);
s=tf('s');
L_array=5:5:50;
figure; hold on;
for i=1:length(L_array)
L=L_array(i);
G=((58.2+11.7*L)*s^2*25^2+(3996.8 + 815.7*L)*s*25+815.7*25^2)/(s^2*(s^2*25^2+126.9*s*25+(3996.8+1.9*25^2)));
CL=feedback(G,1);
pzmap(CL);
end
h = findobj(gca,'type','line');
for jj=2:length(h)
set(h(jj),'MarkerSize',12,'Color',cb(floor(jj/2),:));
end
grid;
colormap(parula);
c=colorbar;
Also the colorbar is inverted i.e. Blue corresponds to larger L and vice versa. I would like to have it inverted! Thanks in advance!
I could not find any handle to the desired objects in the plot. However, I have some additional insights. The grid corresponding to pzmap has, inherently, an sgrid. The handles of this grid do not show up in the gca properties. So you cannot do anything about it. Even the pzoptions does not enable you to modify those settings. Additionally, the additional Y-Ticks correspond to lines of constant natural frequencies.
Alternatively, it is better to use the sgrid command directly. To choose the constant damping lines,
z = [0, 0.25, 0.5, 0.75, 1];
To remove the additional Y-Ticks,
wn = [];
Now, use sgrid and grid command to get whatever you want.
sgrid(z,wn);
grid;
I can't still change any properties of the grid lines associated with sgrid but it still improves the look of the plot. The question is still open to investigation.

How to get variable scales on y axis for same graph in matlab plotting?

I am working on matlab programming, my problem is that in the same graph on y axis i need to have variable scaling, for example from 0.1 to 1 i need to have a gap between scales 0.1, but after 1 I need to have scale gap of 2, is there some command available for the same?
There is an example by The Mathworks on Matlab answers which does pretty much what you want to achieve. The idea is to create 2 axes on the same figure and use one axes to plot some data (eg. for the 0.1:0.1:1 tick marks) and the rest on the other axes. Then you overlay both axes with a transparent background:
%Create two overlapping axes
axes_handle_1 = axes;
axes_position = get(axes_handle_1, 'Position');
axes_handle_2 = axes('Position', axes_position);
%Create some data with a large gap in the x domain
my_x_data = [1:10 25:35];
my_y_data = rand(1, length(my_x_data));
%Plot the two sections of data on different axes objects
plot(axes_handle_1, my_x_data(1:10), my_y_data(1:10))
plot(axes_handle_2, my_x_data(11:end), my_y_data(11:end))
%Link the y axis limits and fontsize property of the axes objects
linkaxes([axes_handle_1 axes_handle_2], 'y');
linkprop([axes_handle_1 axes_handle_2], 'FontSize');
%Set the x range limits and tick mark positions of the first axes object
set(axes_handle_1, 'XLim', [1 21], ...
'XTick', [1 5 10])
%Set the x range limits and tick mark positions for the second axes object.
%Also set the background color to 'none', which makes the background
%transparent.
set(axes_handle_2, 'Color', 'none', ...
'YTickLabel', [], ...
'XLim', [14 35], ...
'XTick', [25 30 35])
It's quite straightforward and to my knowledge there is no built-in way to do it otherwise, except maybe with submissions from the File Exchange. Anyhow if you have questions about the above code please ask!
Please use gca property of matlab. In gca you can set a variable as your scales. Make that variable by merging two different scales
x=[1:80];
y=[.1:.1:8];
figure
plot(x,y);
%First Scale
scale1=[.1:.1:1];
%New scale is being started from 3. If we start from 1, 1 will be repeated
scale2=[3:2:9];
%Merging two variables scale1 and scale2
set(gca,'YTick',[scale1 scale2]);
Please refer http://www.mathworks.in/help/matlab/creating_plots/change-tick-marks-and-tick-labels-of-graph.html
You can also try the idea of scaling one dataset so that it has a similar magnitude as the other data set. Here you can multiply one dataset by 100 (or any suitable scaling parameter), and then it will be similar in size to the other data set. In order to clearly mention which data has been scaled in the graph use the legend.
plot(x,data1,x,100*data2)
legend('data1','100*data2','location','southeast')
Hope this helps.

How to display slope on a plot in 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')).

How to make 1-D plots in MATLAB?

How can I make plots in MATLAB like in below?
I won't need labels, so you can ignore them. I tried using normal 2D plot, by giving 0 to y parameter for each data points. It does help, but most of the plot remains empty/white and I don't want that.
How can I solve this problem?
Edit:
This is how I plot(playing with values of ylim does not help):
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
title('LDA 1D Plot');
ylim([-0.2 0.2]);
hold off
One way to do this would be to adjust the 'XLim', 'YLim', and 'DataAspectRatio' properties of the axes so that it renders as essentially a single line. Here's an example:
data1 = rand(1,20)./2; %# Sample data set 1
data2 = 0.3+rand(1,20)./2; %# Sample data set 2
hAxes = axes('NextPlot','add',... %# Add subsequent plots to the axes,
'DataAspectRatio',[1 1 1],... %# match the scaling of each axis,
'XLim',[0 1],... %# set the x axis limit,
'YLim',[0 eps],... %# set the y axis limit (tiny!),
'Color','none'); %# and don't use a background color
plot(data1,0,'r*','MarkerSize',10); %# Plot data set 1
plot(data2,0,'b.','MarkerSize',10); %# Plot data set 2
And you will get the following plot:
Here's one way to reproduce your figure using dsxy2figxy and annotate. dsxy2figxy can be hard to find the first time, as it is not really in your path. It is part of the MATLAB package and is provided in the example functions. You can reach it by searching for it in the help docs and once you find it, open it and save it to a folder in your path.
h1=figure(1);clf
subplot(4,1,1);
hold on
xlim([0.2,1]);ylim([-1,1])
%arrow
[arrowX,arrowY]=dsxy2figxy([0.2,1],[0,0]);
annotation('arrow',arrowX,arrowY)
%crosses
x=[0.3,0.4,0.6,0.7,0.75];
plot(x,0,'kx','markersize',10)
%pipes
p=[0.5,0.65];
text(p,[0,0],'$$\vert$$','interpreter','latex')
%text
text([0.25,0.5,0.65],[1,-1,-1]/2,{'$$d_i$$','E[d]','$$\theta$$'},'interpreter','latex')
axis off
print('-depsc','arrowFigure')
This will produce the following figure:
This is sort of a hackish way to do it, as I've tricked MATLAB into printing just one subplot. All rasterized formats (jpeg, png, etc) will not give you the same result, as they'll all print the entire figure including where the non-declared subplots should've been. So to get this effect, it has to be an eps, and it works with it because eps uses much tighter bounding boxes... so all the meaningless whitespace is trimmed. You can then convert this to any other format you want.
Ok so the closest I have come to solving this is the following
hax = gca();
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
set(hax, 'visible', 'off');
hax2 = axes();
set(hax2, 'color', 'none', 'ytick', [], 'ycolor', get(gcf, 'color');
pos = get(hax, 'position');
set(hax2, 'position', [pos(1), pos(2)+0.5*pos(4), pos(3), 0.5*pos(4)]);
title('LDA 1D Plot');
hold off
So in short, I hid the original axis and created a new one located at 0 of the original axis, and as I couldn't remove the y axis completely I set it's color to the background color of the figure.
You can then decide if you also want to play with the tick marks of the x-axis.
Hope this helps!
Very naive trick but a useful one.
Plot in 2d using matlab plot function. Then using edit figure properties compress it to whichever axis you need a 1D plot on !! Hope that helps :)

How do I visualize a matrix with colors and values displayed?

I want to create images like this from a double precision matrix using MATLAB.
Sample image:
http://twitpic.com/2xs943
You can create this sort of plot yourself pretty easily using the built-in functions imagesc and text and adjusting a number of parameters for the graphics objects. Here's an example:
mat = rand(5); % A 5-by-5 matrix of random values from 0 to 1
imagesc(mat); % Create a colored plot of the matrix values
colormap(flipud(gray)); % Change the colormap to gray (so higher values are
% black and lower values are white)
textStrings = num2str(mat(:), '%0.2f'); % Create strings from the matrix values
textStrings = strtrim(cellstr(textStrings)); % Remove any space padding
[x, y] = meshgrid(1:5); % Create x and y coordinates for the strings
hStrings = text(x(:), y(:), textStrings(:), ... % Plot the strings
'HorizontalAlignment', 'center');
midValue = mean(get(gca, 'CLim')); % Get the middle value of the color range
textColors = repmat(mat(:) > midValue, 1, 3); % Choose white or black for the
% text color of the strings so
% they can be easily seen over
% the background color
set(hStrings, {'Color'}, num2cell(textColors, 2)); % Change the text colors
set(gca, 'XTick', 1:5, ... % Change the axes tick marks
'XTickLabel', {'A', 'B', 'C', 'D', 'E'}, ... % and tick labels
'YTick', 1:5, ...
'YTickLabel', {'A', 'B', 'C', 'D', 'E'}, ...
'TickLength', [0 0]);
And here's the figure this generates:
If you run into trouble with the x-axis tick labels you choose being too wide and overlapping one another, here's how you can handle it:
Newer versions of MATLAB: Not sure which version this was added, but in newer versions axes objects now have the properties '{X|Y|Z}TickLabelRotation', which allow you to rotate the labels and fit them better.
Older versions of MATLAB: For older versions you can find some submissions on the MathWorks File Exchange that can rotate the tick label text, like XTICKLABEL_ROTATE from Brian Katz.
h = imagesc(magic(8))
impixelregion(h)
http://www.mathworks.com/help/toolbox/images/ref/impixelregion.html
Requires Image Processing Toolbox
If you only care about looking at zero/non-zero entries in your matrix (e.g. if it's sparse), use spy.
Else, use imagesc.
PS: I can't access your image
I expect you could persuade Matlab to draw that, if you look at the File Exchange you may find someone has already written the code. But it would be a lot easier, if you don't have the code, to use MS Excel.
EDIT: So I gave this some more thought and here's what I came up with. I've not mastered posting graphics to SO, so trust me, this will lead you towards a solution. But it would honestly be easier with Excel.
First define a matrix with your data values; I call the matrix G in the following. Then execute the commands:
image(G);
colormap(gray)
Now, I had to do some fiddling around, rescaling the data, to get a good graphic, but this should produce a gray-scale plot with numeric axes. Now, go to your figure window and open the plot tools.
Select the X axis and hit the Ticks button. All you have to do now is edit the labels to the texts that you want. Do the same for the Y axis. Write the numbers in the squares on the plot -- use the Text Box from the Annotations menu.
After a lot of fiddling about you'll have the graphic you want. At this point, I suggest that you choose the menu command File | Generate M-File and do just that. If you want to create such graphics programmatically in future just turn the generated M file into a proper function that does what you want.
But it's still a lot easier in Excel.