Matlab - highlight a specific interval using patch - matlab

I would like to highlight a specific interval in my plot. I found a way using the patch object.
The problem is that my layout gets messy whenever i use it.
Here's an example of a plot:
x = 1:0.05:25;
plot(x,sin(x)+sin(100*x)/3);
xlabel('x axis');
ylabel('y axis');
title('\Omega \Delta test');
legend('sin \Sigma')
And to highlight a period:
yl = ylim;
patch([5 5 10 10],[yl(1) yl(2) yl(2) yl(1)],'k',...
'facecolor',[.4 .6 .4],'edgecolor',[.4 .6 .4],...
'facealpha',0.3,'edgealpha',0.3)
My results with and without the patch command:
Normal:
Messy:
Look at the fonts and the legend block. Any ideas on how to fix that?
Is there a better way to highlight an interval? I need to choose the color and set transparency.
Just one more question: Why do I have to use the third input (color) if it's not applied?
Thanks in advance!

Edit: This answer is only valid for Matlab versions before 2014b, as the incredibly useful erasemode property has been removed from all HG2 graphic objects on later Matlab versions.
I ran into this problem countless times and I had to learn to live with it. Most times I can accept the glitches of the OpenGL renderer if it buys me nice transparency effects, but in some cases it is just not acceptable.
I use patch objects to highlight intervals in many applications, usually over several curves. There is a trick you can use when transparency is not an option, it is the EraseMode property of the patch object. If you set the EraseMode property to 'xor' the patch will not be transparent, yet anything under the patch will xor the patch pixel colours so you can still see the curves under the patch.
This not being a transparency rendering, you can use the default painter renderer and avoid all the occasional glitches of the OpenGL.
So for example with your data:
hp = patch([5 5 10 10],[yl(1) yl(2) yl(2) yl(1)],'k',...
'facecolor','g','edgecolor','g',...
'erasemode','xor') ;
And the nice advantage of this trick is it works with monochrome display/prints. If you cannot use multiple colours, you can use that with only one colour (if you plan black & white printing for publication for example)
hpx = patch([5 5 10 10],[yl(1) yl(2) yl(2) yl(1)],'b',...
'facecolor','b','edgecolor','b',...
'erasemode','xor') ;

(Note: This answer only makes sense if you're using the OpenGL renderer.)
If that's the case, then this is one symptom of
a bug in MATLAB 6.5 (R13) and later versions in the way that axes are rendered in hardware accelerated OpenGL, when transparency is used
as mentioned here.
The simplest workaround is to force OpenGL to run in software mode by including the line:
opengl software
Apparently, this only works under Windows and Linux. For other symptoms of the problem and different approaches to solutions have a look at this related question.
Regarding your other questions:
Not sure if it's a better way, but it's another option: You could use an area-plot like this:
opengl software
figure
x = 1:0.05:25;
ax = plot(x,sin(x)+sin(100*x)/3);
hold on
basevalue = -2;
areaAx = area([5,10],[2,2], basevalue);
set(areaAx, 'FaceColor', [.4 .6 .4])
alpha = get(areaAx, 'Children');
%make area plot transparent
set(alpha, 'FaceAlpha', 0.5);
set(areaAx, 'EdgeColor', 'none');
xlabel('x axis');
ylabel('y axis');
title('\Omega \Delta test');
legend('sin \Sigma')
xlim('auto')
ylim('auto')
hold off
However, OpenGL renderer will also cause problems here, so it's not a fix, just another option.
And finally, I'm not sure what you mean by the color not being used. The 'facecolor' is used, that's why your plot is green. When you go through the area-option above step by step you'll see that you get a solid color first. Later on, transparency is added with the 'facealpha'-option.

Related

how to display the axes outline when using patch to draw a simple rectangle?

I'm trying to draw a simple rectangle in matlab with the patch function. The thing is that once I use the patch function the outline box disapear (It seems to ignore the current axes in the figure). This is the simple code I'm using:
figure
set(gca,'visible','on')
axis([0,20e9,0.25,1.1])
patch([7e9 7e9 10e9 10e9],[.55 .35 .35 .55],'c','FaceAlpha',0.2,'linestyle','--','edgecolor','b','EdgeAlpha',.2,'linewidth',2);
box on
thanks in advance, I'm using the 2013 version of matlab by the way.
So the issue is that since your patch has transparency, MATLAB must change your figure's renderer from the default renderer to OpenGL (which supports transparency). As a result, some features of your graphics (in your case the bounding box on the axes) may appear differently.
If you change the Renderer back to 'painters', you'll see that the box goes back to the way you expect but you lose transparency.
set(gcf, 'Renderer', 'painters')
Unfortunately, there's really no good solution to this. You could consider changing your face color to appear to be transparent but not really and then MATLAB can use the default renderer. You could also try to increase the LineWidth of the axes
set(gca, 'LineWidth', 2)

Matlab: How to plot without color graduation?

My friend has made a script to handle a lot of data and plot various plots, however when he runs the script, the graphs have different colors according to the legend and when I do it, all graphs are similar with a color graduation from black to red! (see picture) Why does it differ and how do I get the graphs in different colors?
2D plot with color graduated graphs:-
figure
hold on
plot(sentar_7.created_at, sentar_7.acc_diff, '-');
plot(sentar_7.created_at, sentar_7.stand_toggle, '-');
plot(sentar_7.created_at, sentar_7.state, '-');
title('Sentar 7 acc')
xlabel('tid')
ylabel('dist [cm]')
legend('acc diff','stand toggle', 'state')
hold off
This is a known issue with certain Intel graphics drivers. One potential workaround is to use basic hardware rendering:
opengl hardwarebasic
You could also disable the AlignVertexCenters property of the line object:
h = findall(gca, 'type', 'line')
set(h, 'AlignVertexCenters', 'off')
The best solution may be to update your graphics drivers to the 4380 version.

add semi-transparency to 2d histogram

I am trying to make a plot like this one:
I want a 2D histogram with bar color proportional to the height and semi-transparent bars.
I tried to put together the examples provided here
x = randn(100, 2);
figure
hist3(x, [20 20]);
colormap(hot) % heat map
grid on
view(3);
%bar color
set(get(gca,'child'),'FaceColor','interp','CDataMode','auto');
%semitransparency
set(gcf,'renderer','opengl');
An example of the result is this:
The semi-transparency is absent.
I do not know if it is a problem of my Matlab version (R2014a) or if ---more probably--- I am messing up something. Maybe the axis handles?
Next
Outside this question: I would also like to add a transparent surface interpolating the histogram values (I got also some problems with this). I think I saw something like this on SO recently, but I cannot find it anymore. Does anyone have some hits?
You didn't actually change the surface transparency in your example. All you did was change renderers. Here's the extra line you would need:
set(get(gca,'child'),'FaceAlpha',0.8);
A value of 1 would be opaque, 0 invisible.
You may also want to change the edge line transparency too:
set(get(gca,'child'),'EdgeAlpha',0.2);

Control the shading of a single surface in matlab without affecting others' FaceColor

I've browsed through this site without finding similar questions (despite similar titles). My problem is as follows. Create a function deleteme that draws a big black patch:
function h = deleteme()
h = surf([0 0; 50 50], [0 50;0 50], [20 20; 20 20], 'FaceColor', [0 0 0]);
end
Now run a script that uses this function along with any other surface creation function.
close all; clear all; clc;
myfig = figure;
hold all
deleteme();
surf(peaks)
colormap(hot(128))
shading interp
hold off
Now the patch isn't black anymore, it's white, because shading interp affected it and assigned its color to the colormap. The problem is that i can't find a way to both interp the peaks (to make it look better) and keep the patch black except:
Calling the black patch later after the colormap
Playing with the colormap and the caxis etc.
My question is: can you modify the function deleteme to prevent this behavior and keep what it draws as it drew it? or can you easily modify the call to surf(peaks) to interp only peaks and not the rest? I'm looking for a solution that makes the deleteme function easy to use without relying on Matlab arcane colormap play in every plot. Of course, deleteme is only a mwe of a much bigger function...
Thanks!
Alright, I failed at modifying the deleteme function to actually keep the pane black after a shading interp. This is really a behavior of shading -- it may be possible to limits its effects.
However I realized that 'interp' is actually one possible argument for 'FaceColor' -- I never used it as such. Thus a temporary fix (until I can really isolate the patch from the call to shading) is to set all surfaces to a manual version of shading interp like this:
surf(peaks, 'EdgeAlpha', 0, 'FaceColor', 'interp')
I'll leave the question open for a while, in case someone wants to pitch in their ideas. I'd still like to know how we can isolate a matlab object from functions like shading, alpha, etc.

How to draw good looking arrows in Matlab?

I have been trying to draw arrows in Matlab in my figure but they all look terrible.
Also, I want my arrowhead to be a solid triangle, not a V.
I tried using the packages available on the Matlab File Exchange: arrow, arrows, arrows3, and probably at least one other one.
I even tried manually creating an arrow in the Matlab figure editor, but when I adjust the line width, the arrow looks like this:
I used the annotation command to create the arrow above:
annotation(gcf,'arrow',[0.621875 0.457916666666667],...
[0.205421152030217 0.40755429650614],...
'HeadLength',4,'LineWidth',5);
Here's the result trying to use the arrow package available here: Arrow.m (notice how the bottom arrow head is not perpendicular to the line:
I even tried the following and here is the result below (notice the terrible looking arrowhead):
figure
plot(1:10, 1:10)
annotation(gcf,'arrow',[0.621875 0.457916666666667],...
[0.205421152030217 0.40755429650614],...
'HeadLength',4,'LineWidth',5);
Vector graphics is hard. Though Matlab's typography is just as bad, but here's a simplistic text-based solution (I refuse to do this sort of annotation in Matlab any more):
figure
plot(1:10, 1:10)
text(5,4,'\rightarrow','FontSize',54,'Rotation',135,...
'HorizontalAlignment','center');
which yields a figure like this
Note that I have used '\leftarrow' because it points in the direction of zero degrees, which makes doing math in my head easier. This is no canned solution, you'll still need to fiddle with position to overcome the fact that Matlab is aligning this as text (see the 'Extent' and 'Margin' properties). Not surprisingly, you may see small glitches. The LaTeX interpreter can be used to obtain a different style arrow head:
text(5,4,'$\rightarrow$','FontSize',54,'Rotation',135,...
'HorizontalAlignment','center','Interpreter','latex');
I don't get the small glitches with this option, but the arrows look different (there are likely other LaTeX arrow styles that could be substituted). Changing the font may also have an effect and there are certainly other text-based arrows that could be used. More details on adding arrows can be found in this article from The MathWorks.
Another solution is to use the open-source Waterloo graphics - a library that addresses this by providing a pure Java library of 2D graphics functions that can easily be integrated in Matlab. See some examples here...
For example, try this code (after properly installing waterloo)
f = GXFigure();
x = -5:0.1:5;
gr1 = gxgca();
a1 = line(gr1, x, cos(x), 'LineSpec','-ob');
b1 = line(gr1, x, sin(x), 'LineSpec','-sg');
annotation(gr1,'arrow',[0.1 0.1],[0.4 0.4],'HeadLength',0.2,'HeadWidth', 0.5, 'LineWidth',2);
gr1.getObject().getView().autoScale();
Having worked with Matlab for more than 10 years and seeing almost zero progress in the quality of the plots (anti-aliased output to bitmap, decent looking eps-files, ...), I decided that my long time solution will be here. Some examples of decent looking arrows here, more beautiful graphs here. Unfortunately, some of the toolboxes prevent me from going completely to numpy/scipy/matplotlib. I know this is more of a rant than an answer, but that is my solution ...
Using quiver or quiver3 for 3-D plots will certainly look better than the that last arrow you made using annotation. I'm not sure it will look much better than the ones you made using the Arrow.m package though. It's possible to change the stlyes on quiver as well if you want.
I resorted to installing InkScape and drawing arrows in there. Nothing beat the simplicity and quality.
InkScape Website
When line-based arrows fail, you can always try patch-based ones:
xArrow = [0 1 1 1.2 1 1 0]; % X-coords of arrow edge points
yArrow = [-0.1 -0.1 -0.2 0 0.2 0.1 0.1]; % Y-coords of arrow edge points
hArrow = fill(xArrow,yArrow, [1 0 0]); % Plot a red arrow
axis equal % Set axis tick marks to be equal
Although more work, you can potentially parameterize the above into a function that takes a number of arguments for adjusting the scaling, aspect ratio, rotation, and position of the arrow. You can even adjust the color, edge line color, and alpha transparency.
This sort of idea appears to have been implemented by François Beauducel in his File Exchange submission ARROWS: generalized 2-D arrows plot.
There is now the DaVinci Draw toolbox (full disclosure: I wrote/sell the toolbox), which uses low-level Matlab commands like plot() and patch() to draw mid-level shapes like arrows. Example syntax:
davinci( 'arrow', 'X', [0 10], ...
'Y', [0 2], ...
'Shaft.Width', 1, ...
'Head.Length', 2.5, ...
'Color', 'w', ...
'EdgeColor', 'k', ...
'LineWidth', 2.5 )
From the documentation: