Plot with variable background color - matlab

I'm plotting line charts with the x-axis representing the timeline. Some of the dataranges should be marked as unreliable. For showig this it would be great to change the background color over these x-ranges to some bringt yellow or red. Is there an option of doing that?
I know that could us gscatter instead of gplot for using colors. But then only the data is colored and not the background and I don't get linecharts but point charts. Colored data would be an acceptable alternative, but I need line charts.

It is always possible to make a filled polygon plot. Try,
a = 0:0.1:1;
b = a;
figure;
plot(a,b,'r');
hold on;
x = [0 0 1 1 0];
y = [0 1 1 0 0];
h = fill(x,y,'g');
set(h,'FaceAlpha',0.1); % or alpha(h,0.1); would also work

Related

How do I customize the picture in matlab legends?

I want to draw a contour plot of a plane and a surface with legends. Plotting two surfaces in the same figure create the same legends. I want to change the resulting ellipses in the legend. Can I draw parallel lines instead of ellipses on the legend chart?
This is a sample source code:
[X,Y] = meshgrid(-3:.1:3);
Z1 = peaks(X,Y);
Z2 = 2*X+3*Y+4;
contour(X,Y,Z1)
colormap jet
shading interp
axis([-3 3 -3 3])
hold on
contour(X,Y,Z2)
legend('surface','plane')
Honestly there's no good way to get an image in front.
There are a few work arounds that I could show you, but you'll have to be specific.
The easiest things are, getting a colorbar or a rectangular box (1 color) infront of text. These are standard options for datatypes/legend entries.
I suggest you start off with giving your surfaces/countours handles.
h1=surf(....);
h2=plot(....);
lgd=legend([h1, h2, ....],[entries']);
For text with white in front you can do
h_separator1 = plot(NaN,NaN,'.','Color',[1 1 1]);
lgd=legend([h_separator1],['text']);
Here's an example you can run that let's you do the things I just said
clear all; % just for ease of quickly plotting this
close all; %closing all figures
myc=[1 1 1; 0 0 0; 1 1 1; 0 0 0; 1 1 1]; %this is want we will use to draw the paralel lines, can be of any color, just replace the zeros, with the respective values of the colors you want, 0 0 0 is black
x = [0 0 0 0]; %making it have 0 area and thus invisible
y = [0 0 0 0];
c = [0 0.33 0.66 1]; %lets you add a colorbar
figure
colormap(myc); %update the figure to use your colormap
hold on
h3 = plot(NaN,NaN,'Color','none'); %blank entry
h4 = plot(NaN,NaN,':'); % entry with dotted line, color "pseudo random"
h1=patch(x,y,'red','EdgeColor','none'); %For a rectangular color entry in legend
h2=patch(x,y,c,'EdgeColor','none'); %lets you add the colorbar, later use to place inside the legend as paralel lines
[lgd,OBJH,OUTH,OUTM]=legend([h1,h3,h2,h4],{'HI your text here','Nothing','paralel lines','line'}); %the lgd handle let's you later modify properties of the legend
hcb=colorbar; %the colorbar can still be modified, to have no number or a different scale, color, etc.
hcm=OBJH(5)
xlim([0 1])
ylim([0 1])
lpos=lgd.Position; % get position legend
lnr=numel(OUTH); %legend entries is useful
lhstp=lpos(4)/(lnr+1); %heigth step
hax=gca;
axpos=hax.Position; %to shift position because the colorbar is placed in the figure and not within the axes in comparison to the legend
% placing at by example 3rd entry
wdentry=0.04; %at the moment trial and error depends on width on legend box which is based on amount of characters and text size.
p1=axpos(1)+lpos(1)+0.01;
p2=lpos(2)+3/2*lhstp;
p3=wdentry;
p4=lhstp-0.01;
hcb.TickLabels=[]; %remove tick labels
hcb.Ticks=[]; %remove ticks
hcb.Color=[1 1 1]; %white border around it to make it "semi-invisible"
hcb.Position=[p1 p2 p3 p4];

Annular ring pattern with alternate bright and dark rings: using matlab

I am attempting to make a pattern consisting of annular rings with radii proportional to the square root of the natural numbers. Also I want the inner most circle to be white followed by a black circle followed by a white and so on.
c = [0 0; 0 0];
r = [5.2494 9.0922];
viscircles(c, r)
r1 = [7.4328 10.4988];
viscircles(c, r1)
I have generated the above code to form the annular ring structure but I want to fill in the color as well. What should I do?
You could go the mathematical route and plot the function ceil(sin(pi*(X.^2 + Y.^2))):
zoomlevel = 50;
for n = 1:zoomlevel
[X,Y] = ndgrid(linspace(-n,n,500));
I = ceil(sin(pi*(X.^2 + Y.^2)));
imshow(mat2gray(I));
drawnow;
pause(0.03);
end
Of course this will only be a raster graphic instead of a vector one, so don't zoom in too much. ;-) (Although the aliasing artefacts will look quite cool if you zoom out. Plot at your own risk.)
My Matlab version doesn't have viscircles, so here's an approach which plots each individual circle with alternating colors. It uses the rectangle function, which lets you define the curvature of the corners so that the rectangle/square becomes an ellipse/circle. Bigger circles should be drawn first, so that they don't completely cover smaller circles.
colors = [.9 .9 .9; 0 0 0]; %// light gray and black
N = 16; %// maximum number
hold on
for n = N:-1:1; %// bigger circles first
s = sqrt(n);
rectangle('curvature', [1 1], 'position', [-s/2 -s/2 s s], ...
'edgecolor', 'none', 'facecolor', colors(mod(n-1,2)+1,:));
end
axis square
You can also create a "surface" with value 1 for all your r radiuses and 0 for the r1. Then either plot as a surface seen form top, or directly use pcolor.
r = [0 5.2494 7.4328 9.0922 10.4988] ; %// define all your radiuses
bw = mod( 1:numel(r) , 2 ) ; %// create an alternance of 0 and 1 (same size as "r")
ntt = 50 ; %// define how many angular division for the plot
theta = linspace(0,2*pi,ntt) ; %// create all the angular divisions
[rr,tt]=meshgrid(r,theta) ; %// generate a grid
z = repmat( bw , ntt , 1 ) ; %// replicate our [0 1 0 ...] vector to match the grid
[xx,yy,zz] = pol2cart(tt,rr,z) ; %// convert everything to cartesian coordinates
pcolor(xx,yy,zz) %// plot everything
colormap(gray(2)) %// make sure we use only 2 colors (black and white)
shading flat ; axis equal %// refine the view (axis ratio and "spokes" not visible)
You can send as many radiuses as you like in the original r.
This will render:
This method look a bit longer at first than other solution, but you could remove many intermediate steps by consolidating some lines, and if you are to reuse the graphics later on, it may present 2 benefits:
if you get the handle of the graphic object (hp=pcolor(xx,yy,zz)), you only have one graphic object to handle.
if you need to change the color, you do not need to cycle through each circle, just change the colormap to the 2 colors you want (for example if you want "red" and "green", just call the colormap colormap([1 0 0;0 1 0]) and you're done.
viscircles returns an hggroup object. One of the properties of such an object is its Children, which is an array of handles to the graphics objects it creates. For instance you could write
h1 = viscircles(c, r)
c1 = h1.Children
The children here should just be the handles to the circular patches defined by viscircles. Now, to set the color of the ith circular patch, you can set the FaceColor property of the handle c1(i).

Matlab custom colormap with only 3 colors

just want to check if it is possible to make a custom colormap with only 3 colors? (there is no need for gradient).
Example: Data ranges from 0-100,
so 0-33 is one color,
34-67 is another color,
and 68-100 is another color.
Just use a colormap with three rows. Each row defines a color in terms of R, G, B components.
A = randi(100,16,16); %// example data
imagesc(A) %// display matrix as image
colormap([1 0 0; 0 1 0; 0 0 1]) %// apply colormap
colorbar %// show color bar
This defines uniformly spaced thresholds between colors. If you need more control you need to have more than three rows, with some of the colors repeated. For example,
colormap([1 0 0; 1 0 0; 0 1 0; 0 0 1]) %// apply colormap
will define a 50% threshold for first color, 75% for second and 100% for third.
Take this example:
% some matrix with integer values in the range [0,100]
Z = peaks;
Z(:) = round((Z(:)-min(Z(:))) ./ range(Z(:))*100);
% show as image (with scaled color mapping)
image(Z, 'CDataMapping','scaled')
caxis([0 100]) % set axes CLim property
colormap(eye(3)) % set figure Colormap property
colorbar % show colorbar
Note that the colors are scaled to the range [0 100], that range is mapped to the current figure's colormap (which we set to only three colors).
Follow this example: How to create a custom colormap programmatically? but instead of R = linspace(0,t(1),50)' you would use R = ones(50,1)*t(1)
or even simpler:
if colour 1 is t1 = [r1, g1, b1] etc then
map(1:34, :) = repmat(t1, 33, 1)
map(35:68, :) = repmat(t2, (67-34), 1)
etc...
OR
map(1:34, :) = bsxfun(#times, t, ones(33,3))
etc...
Check my answer here
You can use that code and decide to interpolate between values or not, its just 2 lines of the code.
The result image shown in the original post for a GYR cutom colormap.

How can I change the color of bars in bar graph?

I'd like to create a bar graph where I change the color of some bars.
The code for my bar graph is the following:
y = [0.04552309, -0.001730885, 0.023943445, 0.065564478, 0.032253892, 0.013442562, ...
-0.011172323, 0.024595622, -0.100614203, -0.001444697, 0.019383706, 0.890249809];
bar(y)
I want the first six bars to be black and the last 6 bars to be blue, but I have no idea how to do it.
You need to plot them separately (but on the same axes):
bar(1:6,y(1:6),'k')
hold on
bar(7:numel(y),y(7:end),'b')
set(gca,'xtick',1:numel(y))
As the answer from HERE suggests, since the version MATLAB R2017b, you can do so through the CData property. You can find more at THIS documentation page.
Simply put, using the following approach will get you what you need.
b = bar(rand(10,1));
b.FaceColor = 'flat';
% Change the color of the second bar. Value assigned defines RGB color value.
b.CData(2,:) = [.5 0 .5];
The following is adapted from Bar plot with bars in different colors on MATLAB Central:
y= [0.04552309, -0.001730885, 0.023943445, 0.065564478, 0.032253892, 0.013442562, -0.011172323, 0.024595622, -0.100614203, -0.001444697, 0.019383706, 0.890249809];
for ii=1:12
h = bar(ii-0.5, y(ii));
if ii == 1
hold on
end
if ii<=6
col = 'k';
else
col = 'b';
end
set(h, 'FaceColor', col,'BarWidth',0.4)
end
axis([0 12 -0.2 1])
hold off
No need to plot separately, here is the simple solution:
y= [0.04552309, -0.001730885, 0.023943445, 0.065564478, 0.032253892, 0.013442562, -0.011172323, 0.024595622, -0.100614203, -0.001444697, 0.019383706, 0.890249809];
figure,
bar(y)
y1 = zeros(1,length(y));
y1(3:5) = y(3:5);
hold on
h = bar(y1)
set(h, 'FaceColor', 'k')
See output
Very late as usual, but there is an easy way to 'trick' matlab.
You first define your colormap (for instance 3 different colors):
mycolors = lines(3) % or just specify each row by hand
Then you plot your bars in the following way:
bar(x,diag(y),'stacked'); % x will be usually defined as x = 1:number_of_bars
colormap(mycolors);
That's all. The magic comes from the diag function together with the 'stacked' tag that makes matlab think you have more data (but they are all 0).

How to combine a custom color range with colorbar in MATLAB?

I'd like to have a surface plot like the one below, but with a proper colorbar.
This is my code:
[X,Y,Z] = peaks(30);
[maxval dummy] = max(Z(:));
[minval dummy] = min(Z(:));
crange = 1.5;
% red, yellow, green
cmap = [1 0 0; 1 1 0; 0 1 0];
colormap(cmap);
colors = zeros(size(Z));
colors(Z <= -crange) = 1; % red (1)
colors(Z > -crange & Z < crange) = 2; % yellow (2)
colors(Z >= crange) = 3; % green (3)
surf(X,Y,Z, colors);
axis([-3 3 -3 3 -10 10]);
%cbh = colorbar('YGrid','on');
%caxis([minval-0.1 maxval+0.1]);
%set(cbh,'YTick',[minval -crange crange maxval]);
So far I had no luck in adding a colorbar where the colors (green,yellow,red) are aligned according to my custom range (green[8 ... 1.5],yellow[1.5 ... -1.5], red[-1.5 ... -6.4]). Instead, when I uncomment the last three lines,
a colorbar with linearly aligned colors shows up and the colors in my plot are aligned according to the colorbar and not to my custom range.
Now, what I'd like to have is that the colors in the colorbar match my custom ticks and that the plot looks like in the first picture.
The problem is that you specify the colors of each point in the surf plot by yourself, so they're not related to the z-value as is by default. The colorbar therefor is constructed only based on the color numbers, being 1 to 3. These therefor also show up as the default ticks of the colorbar (before you change them.
As you found out, you can set the ticks manually, and in the same way you can 'cheat' and use yticklabels:
figure
colormap(cmap);
surf(X,Y,Z, colors);
axis([-3 3 -3 3 -10 10]);
cbh = colorbar('YGrid','on');
set(cbh,'ytick',linspace(1,3,4));
set(cbh,'yticklabel',arrayfun(#num2str,[minval -crange crange maxval],'uni',false));
Or another way is to simply use caxis, but then the colors of the plot are linearly defined by the minmax values. So with this you can't set your non-linear ranges.
Illustration:
figure
colormap(cmap);
surf(X,Y,Z);
axis([-3 3 -3 3 -10 10]);
caxis([minval-0.1 maxval+0.1]);
cbh=colorbar
set(cbh,'YTick',[minval -crange crange maxval]);
So after all, I think my first method (using yticklabels) is the only way of doing what you want.
I know this is a crazy old post, but it came up as I was looking for answers. And here would be my answer (which has to assume unfortunately that the graduations on the color bar are equal size).
So given that you have made the color map, which is only 3 colors, the next part is algebra. The caxis follows a simple formula which is determined by the how many colors are in the color bar, and your min and max range.
index = fix((C-cmin)/(cmax-cmin)*m)+1;
So index will refer to the index in the color map (m = 3 since that is the length of your colormap), and what I would do is make C= 1.5, decide if you want it symmetrical (you are solving for cmax and cmin and is easier if both are x), and make index=2 (since you only have 3 colors, that should mean solving for 1.5 would give you the cmin/cmax to set which would make 1.5 the cutoff between yellow and red. You should be able to set the display range value somewhere, which will set the colormap appropriately (though probably not the labels).
Sorry to reply to such an old post, but maybe this will help others.
I came across this question when finding solutions for a problem that I had. Anyway this question helped me to get a solution for my problem after making little modifications on written codes.
At the same time I like to suggest some changes for the code so that user can get the required plot with necessary colors and the appropriate color bar also.
Here is the code,
[X,Y,Z] = peaks(30);
[maxval dummy] = max(Z(:));
[minval dummy] = min(Z(:));
crange=1.5;
% red, yellow, green
cmap = [1 0 0; 1 1 0; 0 1 0];
colormap(cmap);
colors = zeros(size(Z));
colors(Z <= -crange) = minval-0.1; % red (1)
colors(Z > -crange & Z < crange) = crange; % yellow (2)
colors(Z >= crange) = maxval+0.1; % green (3)
surf(X,Y,Z, colors);
axis([-3 3 -3 3 -10 10]);
cbh = colorbar('YGrid','on');
caxis([minval-0.1 maxval+0.1]);
set(cbh,'YTick',[minval -crange crange maxval]);
Plot