You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
How to include arrows as pointers of a particular point in plot?
134 views (last 30 days)
Show older comments
I have a graph for 3 variables as shown here. I know the saturation point co-ordinates and want arrows of the same color to be pointing them exactly like I have hand drawn in the figure. I tried annotations(arrow) function but it did not work even though I used correct co-ordinates it makes the arrow out of the boundary or maybe I was using it in a wrong way. Please help me if I can draw the arrows at a particular point I need. I would also have to declare 3 set of (x,y) co-odrinates since my main function needs to work simultanously for the three variables.
Code I tried:
plot(T,ih,T,iv,T,sh)
legend('Infected Human','Infected Mosquito','Susceptible Human','Location','east')
xlabel('Time (days)')
ylabel('Population')
x=[39636/40000 39636/40000];
y=[1 180/200];
annotation('arrow',x,y)
Thank you very much in advance.
4 Comments
the cyclist
on 15 May 2020
Can you share the code you used to make the figure, including the "wrong" annotation attempt? That would help us show you what went wrong.
Abhishek Singh
on 15 May 2020
@the cyclist I have edited the code. I have included the part that I am writing for the arrow. Thank you :)
Rik
on 15 May 2020
It looks like your coordinates are around (1,1), which doesn't match the graph you've drawn. They are also relatively close, so the arrow will be small. Did you zoom in?
Abhishek Singh
on 15 May 2020
It is drawing but outside the boundaries. Even if my co-ordinates are at the end it should not be drawing outside is what I thought. See the arrow incircled below.
Accepted Answer
Ameer Hamza
on 15 May 2020
annotation() takes position in figure() coordinates. The position has no relation with the x-values and y-values of your axes. If you want to specify the position of your arrows in the axes() coordinates, then you need to do a transformation. The following code shows an example. The arrow_x and arrow_y specify the position of arrows according to the x-axis and y-axis of the axes() and then use interp1 to do the transformation
fig = figure('Units', 'normalized');
ax = axes();
plot(1:10, 0.1:0.1:1);
pos = ax.Position;
pos(3:4) = pos(3:4) + pos(1:2);
arrow_x = [5 5];
arrow_y = [0.7 0.5];
arrow_x_fig = interp1(ax.XLim, pos([1 3]), arrow_x);
arrow_y_fig = interp1(ax.YLim, pos([2 4]), arrow_y);
annotation('arrow', arrow_x_fig, arrow_y_fig);
17 Comments
Abhishek Singh
on 16 May 2020
Do you mean I have transform my equation to set it in (0,1)?
I did not exactly understand what is being done here. Apologies for that.
pos = ax.Position;
pos(3:4) = pos(3:4) + pos(1:2);
Ameer Hamza
on 16 May 2020
No, you don't need to change your equation. My code shows you how you can specify the coordinates using your equation and convert it into the figure coordinates. Note that the figure coordinates vary between 0 and 1. (0,0) at the bottom left and (1,1) at the top right. The lines in your comments find the position of axes() in figure coordinates and then use the xlim and ylim of the axes to find the location in the figure coordinate. Note that I specified the position of arrow like this
arrow_x = [5 5];
arrow_y = [0.7 0.5];
The values are given according to my equation. The next two lines
arrow_x_fig = interp1(ax.XLim, pos([1 3]), arrow_x);
arrow_y_fig = interp1(ax.YLim, pos([2 4]), arrow_y);
These lines convert them to figure coordinate and return values between 0 and 1.
Abhishek Singh
on 16 May 2020
I searched for pos() and I think it is position but could not still understand how it is working here. Interp1 has to do with intercept but somehow I can not understand what these set of codes are collectively doing. Also what does pos(3:4) for example mean and what is the significance of this line specifically. I am not able to understand this line and hence the subsequent steps too.
pos(3:4) = pos(3:4) + pos(1:2);
Ameer Hamza
on 16 May 2020
pos() is not a MATLAB function. It is the name of the variable I created. In MATLAB, the coordinate of the figure window is normalized (because I used 'Units', 'normalized' in my code). (0,0) coordinate is the bottom-left corner, and (1,1) is top-right coordinate. All the points in between can be represented as pairs (x,y) both x and y are less than 1.
Since the axes() object exist inside the figure window. Therefore, it gets a position w.r.t. to figure the window. See here how the position of axes is defined: https://www.mathworks.com/help/matlab/ref/matlab.graphics.axis.axes-properties.html#budumk7_sep_shared-Position
pos(3:4) are the width and height of the axes. To the line [pos(3:4) + pos(1:2)] converts the height and width to the coordinate of the top-right corner of axes object.
interp1 is not used for intercept. It is used for interpolation. You can see some examples to learn how it works.
Abhishek Singh
on 16 May 2020
I am extremely sorry for asking something that would be very basic here. Previously I was thinking I was not just getting bits and pieces but now by your answer I guess I do not understand anything here. Particularly I was thinking that pos(3:4) and pos(1:2) has to do with it but I see that all functions have some specific role which I thought wrongly. I will look at the functions and the link. Thank you very much.
Ameer Hamza
on 16 May 2020
I would recommend running each line, see the output and search documentation until that output starts making sense. Alternatively, you can just treat it as a black box and encapsulate it in a function so that you can use it for your work now, and then you can understand it later. For example, create the following function file
function arrow_handle = myArrowFunction(ax, x, y)
pos = ax.Position;
pos(3:4) = pos(3:4) + pos(1:2);
X = interp1(ax.XLim, pos([1 3]), x);
Y = interp1(ax.YLim, pos([2 4]), y);
arrow_handle = annotation('arrow', X, Y);
end
and then you can call this function whenever you want to plot an arrow
fig = figure('Units', 'normalized');
ax = axes();
plot(1:10, 0.1:0.1:1);
arrow_x = [5 5];
arrow_y = [0.7 0.5];
myArrowFunction(ax, arrow_x, arrow_y);
Abhishek Singh
on 16 May 2020
Edited: Abhishek Singh
on 17 May 2020
I can use it as a function as you suggested but I do not understand the core of it. I mean very basic things like why is it pos(3:4) = pos(3:4) + pos(1:2); Why could it not be pos(4:5) = pos(3:4) + pos(1:2); I mean basically what do each entity mean inside it. I am looking at some sine cosine plots where they are using interp1. But I am not sure how interp1 function is using the pos here.
In short I am not able to translate it in the way I should do it for my code. You end points for x and y are (5 5) and (0.7 0.5) however mine are something like (39000 39000) and (200 180). So does it mean I have to transform these numbers to 1 ? That is the reason I am not able to understand how to translate them to my code. I checked a little bit about these functions and could not make sense of them.
Abhishek Singh
on 18 May 2020
I did it as you suggested and can get an arrow on one of the chart out of three. If I give three set of co-ordinates I will get it on all the three. Is there any way to accomodate three set of co-ordinates in your function?
Ameer Hamza
on 18 May 2020
This updated function is able to plot multiple arrows. You just need to specify the x-coordinates and y-coordinates of end-points of the arrows in arrow_x and arrow_y
fig = figure('Units', 'normalized');
ax = axes();
plot(1:10, 0.1:0.1:1);
arrow_x = [5 5; 6 5; 4 5];
arrow_y = [0.7 0.5; 0.7 0.5; 0.7 0.5];
myArrowFunction(ax, arrow_x, arrow_y);
function arrow_handle = myArrowFunction(ax, x, y)
pos = ax.Position;
pos(3:4) = pos(3:4) + pos(1:2);
X = interp1(ax.XLim, pos([1 3]), x);
Y = interp1(ax.YLim, pos([2 4]), y);
arrow_handle = gobjects(1, size(x,1));
for i=1:size(x,1)
arrow_handle(i) = annotation('arrow', X(i,:), Y(i,:));
end
end
Abhishek Singh
on 18 May 2020
Great! Thanks Ameer. It is working for the three graphs. I would treat it as a black box as you suggested and get back to you in future if I have any questions. Hopefully I won't have to. I am trying to pass colors in annotation() but it seems to not work like that. For now it is just black arrows. Is there any way I can make arrows the same color as the plots they are pointing to ?
Ameer Hamza
on 18 May 2020
Yes, you can treat it as a black box for now. The following shows how to pass colors to the annotation
fig = figure('Units', 'normalized');
ax = axes();
plot(1:10, 0.1:0.1:1);
arrow_x = [5 5; 6 5; 4 5];
arrow_y = [0.7 0.5; 0.7 0.5; 0.7 0.5];
colors = {[1 0 0], [0 1 0], [0 0 1]}; % RGB colors
myArrowFunction(ax, arrow_x, arrow_y, colors);
function arrow_handle = myArrowFunction(ax, x, y, colors)
pos = ax.Position;
pos(3:4) = pos(3:4) + pos(1:2);
X = interp1(ax.XLim, pos([1 3]), x);
Y = interp1(ax.YLim, pos([2 4]), y);
arrow_handle = gobjects(1, size(x,1));
for i=1:size(x,1)
arrow_handle(i) = annotation('arrow', X(i,:), Y(i,:), 'Color', colors{i});
end
end
Abhishek Singh
on 18 May 2020
Thanks Ameer and thanks Rik. I am getting the colors as I can change them accordingly. Ameer, just one thing I tried the code line by line and could work through it. I also played around with the pos() that you have created and just could not figure out what is it with the 3:4=3:4 + 1:2 and then later when they are passed in interp1(). If you could explain in one line about the specific choices for the numbers 3:4, [1 3], [2 4] then it would clear for me but if it will take longer explaining then please ignore this comment :)
Ameer Hamza
on 18 May 2020
pos() is not a MATLAB function. It is an array that has 4 elements. This link explains what do the four elements represent https://www.mathworks.com/help/matlab/ref/matlab.graphics.axis.axes-properties.html#budumk7_sep_shared-Position. They are used to define the location of the axes. The third and fourth elements of the array represent the width and height of the axes object. Adding ([3 4]) with ([1 2]) converts the width and height of the axes object into absolute position in the figure coordinate.
Abhishek Singh
on 18 May 2020
Thanks Ameer. I think now I understand it. I am sorry that I did not read that link attentively in order to just solve this previously. Since left and width are associated with the x axis that is the reason 1 and 3 are used there and similarly for y axis. I also now understand a little what you meant by adding the pos(). I knew it was not function and it explores the axes position but now it makes a little sense to me.
Thank you very much.
G Dalzell
on 29 Jul 2021
This is a good clear answer but it would be good if mathworks could expand the annotation functionality so that a specific data point that has been plotted can be specified as the arrow end point.
Adam Danz
on 29 Jul 2021
Edited: Adam Danz
on 29 Jul 2021
Annotation support for data units has been requested numerous times over the years but has not been addressed by MathWorks.
Arrows can be added with the text() function which operates in data units. One option is using TeX markup,
hold on; xlim([0,1])
plot(.5, .5, 'o')
text(.5, .5, '\downarrow', 'FontSize', 24, 'VerticalAlignment', 'bottom', 'HorizontalAlignment','Center')
plot([.2 .8], [.5 .5], 's')
text(.2, .5, char(8595), 'FontSize', 24, 'VerticalAlignment', 'bottom', 'HorizontalAlignment','Center')
text(.8, .5, char(8675), 'FontSize', 24, 'VerticalAlignment', 'bottom', 'HorizontalAlignment','Center')
More Answers (1)
Rik
on 18 May 2020
A completely different strategy would be to use the LaTeX interpreter to insert an arrow as a text object:
x = 0:pi/20:2*pi;
y = sin(x);
plot(x,y)
text([pi pi*2],[0 0],'\downarrow',...
'FontSize',40,...
'VerticalAlignment','bottom','HorizontalAlignment','center')
20 Comments
Abhishek Singh
on 18 May 2020
I tried this and it works. I did not exactly understand what you meant by LaTex interpreter here?
Adam Danz
on 18 May 2020
I prefer this method to the annotation method since there isn't a need for coordinate transformation.
Here are some additional arrows to try out using Rik's example but they require explicitly setting the interpretter to latex.
text([pi pi*2],[0 0],'\big\downarrow','Interpreter','Latex', ... )
... '\Big\downarrow' ...
... '\bigg\downarrow' ...
... '\Bigg\downarrow' ...
Abhishek Singh
on 18 May 2020
Thanks Adam and Rik. So it would also work for multiple set of co-ordinates?
Adam Danz
on 18 May 2020
Rik's example uses >1 coordinate.
The best way to get that answer is just trying it :)
text(0:.1:1,0:.1:1,'\downarrow')
Abhishek Singh
on 18 May 2020
Hi Adam. I am so sorry. I drew it and it had two arrows and I was so lost that I still asked it. Very silly of me. This is great. Very easy and just need to declare the co-ordinates. Thank you very much to you and Rik.
Adam Danz
on 18 May 2020
% For 1 color used in all arrows
th = text(0:.1:1,0:.1:1,'\downarrow','color','r');
% To define the color of each arrow.
th = text(0:.1:1,0:.1:1,'\downarrow');
colors = jet(11); % Generate the color matrix any way you want.
% The color matrix must have the same number of rows as arrows.
set(th,{'Color'}, mat2cell(colors,ones(size(colors,1),1),3))
Abhishek Singh
on 19 May 2020
How can I use the colors according to my preference? I made jet(3) and then ran it. I am getting different colors. Now if I want to change it according to my graphs or say color of my choice then do I need to change the matrix or just changing something in jet() would do it?
Abhishek Singh
on 19 May 2020
I read about it and understood about the three columns being the normalized values of RGB as you mentioned. What I could not do was if suppose I have jet(3) this always gives me the same output. Can I not set it so I get myself three different resultant colors of my choice.
Adam Danz
on 19 May 2020
Check out the documentation for colormap. jet() is one of more than a dozen color maps. Plus you can create any custom color map you want.
Abhishek Singh
on 22 May 2020
I am sorry Adam. I looked at it and could not understand how it works to choose simply just 3 colors. It has many other links which set helps to set voltages and what not. jet(3) by default was selecting some three random colors. I wanted simply Red Green and Blue for me which I do not understand how it will.
Abhishek Singh
on 22 May 2020
Hi Adam, I used HSV and got the desired colors. Thank you very much to both of you :)
Adam Danz
on 22 May 2020
Glad I could help.
By the way, red, blue green would be
c = [ 1 0 0;
0 0 1;
0 1 0];
Abhishek Singh
on 24 May 2020
I did not know that the matrix in jet could be changed accordingly. I just used some different functions like cool, hot and then eventually HSV gave me my desired colors. I understand the binary numbers here but can we edit jet matrices according to our choice?
Rik
on 24 May 2020
A colormap is a three-column array. The columns are the intensity of red green and blue on a scale from 0 to 1. Every row is a color in your map.
Given this definition, I don't really understand what you mean.
Abhishek Singh
on 24 May 2020
I meant that I used jet(3) as suggested by Adam and I thought the default colors are the ones that could not be changed so I used other options like "cool", "hot" and finally "HSV" game the RGB that I wanted. I did not know that even using the jet(3) we can get the desired color and hence I was asking how to do that.
Adam Danz
on 24 May 2020
jet(n) produces an nx3 matrix of R,G,B color values. The range of colors is always the same. The only input, n, controls the interval.
I recommended running "doc jet" which explains this. As I mentioned earlier, you can create any color map with an nx3 matrix of values between 0 and 1.
Red is [1 0 0] because it's 100% red, 0% green, 0% blue.
Tongyao
on 23 Aug 2023
Just wanted to add a note here. I attempted to add tilted arrow such as `\nwarrow`. It is part of the Latex default arrow but MATLAB does not support it without additional packages.
See Also
Categories
Find more on Formatting and Annotation in Help Center and File Exchange
Tags
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)