Drawing a rectangle over existing plot

I have a subplot in Matlab with two plots. (first picture) I want to draw boxes as seen in the second picture, for specific xvalue ranges. I tried annotation however it does not span all plots. Anybody able to help me?

3 件のコメント

Adam Danz
Adam Danz 2020 年 7 月 28 日
" I tried annotation however it does not span all plots."
If that's the only problem, it sounds like you applied the annotation incorrectly. Annotation is the way to go.
gummiyummi
gummiyummi 2020 年 7 月 31 日
Sorry, I didn't put enough detail about what I had tried....
My problem is the dimension [ ] for each annotation. Since, my rectangle is supposed to envelope a specific x value and +- 5 seconds, I do not know how to format that as a varying dimension
Adam Danz
Adam Danz 2020 年 7 月 31 日
編集済み: Adam Danz 2020 年 8 月 4 日
That's a clearer problem; and a tough one.
The annotation function has been around for a long time and many people have requested that the function accept location values in data-units rather than normalized figure units. Obviously these wishes have never been granted.
See answer for a cleaner solution.

サインインしてコメントする。

 採用された回答

Adam Danz
Adam Danz 2020 年 7 月 31 日
編集済み: Adam Danz 2020 年 8 月 3 日

2 投票

To use an annotation object in the way you're describing, you'd need to convert the data units, which are relative to the axes, to normalized figure units. Though this is possible, it often leads to headaches since a bunch of minor details turn out to be important such as setting axis limit and figure resizing.
The cleaner approach is to highlight the sections within the axes using the original data units.
Here's a demo that you can apply to your project.
% Set up a figure with two subplots and identical x-axes
figure()
sp(1) = subplot(2,1,1);
x = 0:10:1400;
y = randi(400,size(x))+200;
plot(x, y, '.')
xlim([0,1400])
ylim([200,600])
sp(2) = subplot(2,1,2);
y2 = rand(size(x))*5-1;
plot(x,y2,'.')
linkaxes(sp, 'x') % Link the x axes
ylim([-1,4])
% Define rectangle center and +/-d
rectCnt = 590;
rectDelta = 25; % +/-25 from center
% Draw rectangle in upper axes
rectX = rectCnt + rectDelta*[-1,1];
rectY = ylim([sp(1)]);
pch1 = patch(sp(1), rectX([1,2,2,1]), rectY([1 1 2 2]), 'r', ...
'EdgeColor', 'none', 'FaceAlpha', 0.3); % FaceAlpha controls transparency
% Copy rectangle to 2nd axes and adjust y limits
pch2 = copyobj(pch1, sp(2));
rectY2 = ylim(sp(2));
pch2.YData = rectY2([1 1 2 2]);
If you plan on moving the rectangles around, you can link their XData properties so you only need to change one of them and the other one will follow.
linkprop([pch1, pch2], 'XData')
% now slide the bar to the right by 100 units
% and see what happens...
pch1.XData = pch1.XData + 100;

15 件のコメント

gummiyummi
gummiyummi 2020 年 8 月 4 日
Thanks for the help! sorry for my late response....
I am still a bit confused on the following part:
pch1 = patch(sp(1), rectX([1,2,2,1]), rectY([1 1 2 2])
what exactly are [1,2,2,1] and [1 1 2 2] ?
Adam Danz
Adam Danz 2020 年 8 月 4 日
Matlab has great documentation. Check out the description for X and Y in the link below.
The variable rectX defines the left and right boundaries of the red rectangles. The variable rectY defines the lower and upper boundaries. The X and Y inputs to patch() are the (x,y) coordinates of the rectangle. rectX([1 2 2 1]) and rectY([1 1 2 2]) define the 4 corners.
gummiyummi
gummiyummi 2020 年 8 月 4 日
what are the maximum values these coordinates can take? I tried out different ones but I get errors that "index exceeds the number of array elements"
Adam Danz
Adam Danz 2020 年 8 月 4 日
What coordinates?
The 1s and 2s are the index values of rectX and rectY. Those two variables only contain 2 values (look at their values). Are you trying to index those variables with indices greater than 2?
Adam Danz
Adam Danz 2020 年 8 月 4 日
編集済み: Adam Danz 2020 年 8 月 4 日
Unlike many other programming language, Matlab indexing starts with 1, not 0. To access the first value in a vector, you must use v(1). Indexing syntax v(0) will give you an error.
Does this answer your question?
gummiyummi
gummiyummi 2020 年 8 月 4 日
okay so..
if I understand correctly, the rectangle has dimensions in following order?
1) bottom left corner
2) bottom right corner
3) top right corner
4) top left corner
Adam Danz
Adam Danz 2020 年 8 月 4 日
In my example, yes.
You could create any shape using patch and for the rectangle, those coordinates could be in a different order as well. For example,
1) top right corner
2) top left corner
3) bottom left corner
4) bottom right corner
gummiyummi
gummiyummi 2020 年 8 月 4 日
ah ok!
thank you very much!!
Adam Danz
Adam Danz 2020 年 8 月 4 日
編集済み: Adam Danz 2020 年 8 月 4 日
Glad I could help.
It might be helpful to go through some examples using patch().
gummiyummi
gummiyummi 2020 年 8 月 7 日
I want to change the patch outline color but keep getting error that there are "not enough input arguments"
red=[1 0 0];
rectangle_ax(1) = patch(ax(1),rectangle_X([1 1 2 2]),rectangle1_Y([1 2 2 1]),'FaceVertexCData',red,'EdgeColor','flat','FaceColor','none','LineWidth',1);
can you help?
Adam Danz
Adam Danz 2020 年 8 月 7 日
編集済み: Adam Danz 2020 年 8 月 7 日
If you look at the documentation, the patch() function requires at least 3 inputs before the name-value parameters start.
The use of FaceVertexCData is also incorrect since the number of colors listed for FaceVertexCData must be equal to the number of vertices when MarkerFaceColor is flat.
You're missing the color input. See my example again.
If you want to change the outline color,
pch1 = patch(sp(1), rectX([1,2,2,1]), rectY([1 1 2 2]), 'r', ...
'EdgeColor', 'k', 'FaceAlpha', 0.3); % FaceAlpha controls transparency
% ^^^^^^^^^^^^^^^^
% Also see EdgeAlpha
Carlos Quispe Galdos
Carlos Quispe Galdos 2022 年 7 月 16 日
Hello Adam, what does the argument [1,2,2,1] for rectX and [1 1 2 2] for rectY mean?
Adam Danz
Adam Danz 2022 年 7 月 18 日
Good question @Carlos Quispe Galdos. They are not input arguments, they are indices. rectX and rectY are 1x2 vectors. rectX([1,2,2,1]) ask for the first, second, second, first values of the vector.
Carlos Quispe Galdos
Carlos Quispe Galdos 2022 年 7 月 30 日
Excellent Adam! Thank you
Afiq Azaibi
Afiq Azaibi 2023 年 3 月 17 日
編集済み: Afiq Azaibi 2023 年 3 月 17 日
In addition to Adam's solution, starting in R2023a you can use the xregion or yregion functions:
% Set up a figure with two subplots and identical x-axes
figure()
sp(1) = subplot(2,1,1);
x = 0:10:1400;
y = randi(400,size(x))+200;
plot(x, y, '.')
xlim([0,1400])
ylim([200,600])
sp(2) = subplot(2,1,2);
y2 = rand(size(x))*5-1;
plot(x,y2,'.')
linkaxes(sp, 'x') % Link the x axes
ylim([-1,4]);
xregion(sp(1), 565, 615, 'FaceColor', 'r');
xregion(sp(2), 565, 615, 'FaceColor', 'r');
You can also set the EdgeColor properties to emphasize the edges but the default EdgeColor is 'none'.

サインインしてコメントする。

その他の回答 (1 件)

Vahidreza Jahanmard
Vahidreza Jahanmard 2023 年 11 月 14 日

0 投票

To plot the rectangles, you can use this:
% do all your plots
annotation('rectangle',[x y w h]);
for x, y, w, and h, you can plot one time and set the place of the rectangle manually and copy the position to your code

カテゴリ

ヘルプ センター および File ExchangeAxes Appearance についてさらに検索

質問済み:

2020 年 7 月 28 日

回答済み:

2023 年 11 月 14 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by