Matlab adjusting heat map axes and colors - matlab

I'm trying to create a heat map which is something I'm not very familiar with. I have a large matrix of the form:
One=
[0 2 4 6 8
2 1 3 5 6
4 5 8 3 1
6 2 7 4 8
8 3 9 5 4]
And I want to create a heat map such that the topmost row and the leftmost column are the axes.
So far I've managed this:
figure(1)
Plot = One;
colormap('hot');
imagesc(Plot);
I've also noticed that in the 'hot' colormap, the small numbers are very dark and the large numbers are white. Is there a way to reverse that?

Here a good start:
One = ...
[0 2 4 6 8
2 1 3 5 6
4 5 8 3 1
6 2 7 4 8
8 3 9 5 4];
figure();
imagesc(One(1,:), One(:,1), One(2:end,2:end));
get(gca(), 'ydir', 'normal')
colormap(flipud(hot()));
colorbar();
Notice that the x & y axis are larger than the data, so perhaps one needs to exclude One(1,1):
figure();
imagesc(One(1,2:end), One(2:end,1), One(2:end,2:end));
get(gca(), 'ydir', 'normal')
colormap(flipud(hot()));
colorbar();

Generate the colormap with the hot function and flip it upside down with flipud:
colormap(flipud(hot))
By default this produces 64 colors. If you want to specify a different number, say 128, use
colormap(flipud(hot(128)))

Related

How to plot a 3D heatmap or histogram over an image in matlab?

I have this type of data:
Data = [1:1:9; 1 2 3 4 5 6 7 8 9; 1 2 3 4 5 6 7 8 9 ;1 2 3 4 5 6 7 8 9;1 2 3 4 5 6 7 8 9];
Where the first entry is the zone of interest (9 zones total) and the remaining 4 array entries are how long something stayed in the zone (just arbitrary now for this question.
I want to plot how long each thing is in each zone on a picture of a map as a 3d "heatmap" style plot. The map is divided into a 3x3 grid like so:
1 2 3
4 5 6
7 8 9
How do I plot this? I have tried the contour and surf functions but I am not sure how I would map them to the grid. I would like to overlay the graph on a map picture as my final step but just getting the graph up and running would be great!
You can use imagescfor the 2D version or bar3 for the 3D version, in this example I created some subplots, but of course you are free to change this option.
Data = [1:1:9; 1 2 3 4 5 6 7 8 9; 1 2 3 4 5 6 7 8 9 ;1 2 3 4 5 6 7 8 9;1 2 3 4 5 6 7 8 9];
M = zeros(3,3);
2D
for ii = 2:size(Data,1)
subplot(2,2,ii-1)
M(1:end) = Data(ii,:);
imagesc(M)
colormap jet
shading flat %for an exact result
% shading interp %for a smooth result
end
figure
3D (even if I think that the 3D view is useless)
for ii = 2:size(Data,1)
subplot(2,2,ii-1)
M(1:end) = Data(ii,:);
h{ii} = bar3(M)
colorbar
for k = 1:length(h{ii})
zdata = h{ii}(k).ZData;
h{ii}(k).CData = zdata;
h{ii}(k).FaceColor = 'interp';
end
end
I'm not sure if this is the kind of plot that you want, but you could use Delaunay Triangulation to map your duration data as a surface over your grid points. The MatLab file exchange has a nice function for mapping something using this method.
Making Surface Plots from Scatter Data

plot two histograms (using the same y-axis) and a line plot (using a different y-axis) on the same figure

How can I plot two histograms (using the same y-axis) and a line plot (using a different y-axis) on the same figure? I am using Matlab 2014b. I am aware of this but it seems to only work for bar plots?
This is my histogram code:
A = [1 2 2 2 3 4 5 5 5 5 5 5 5 5 5 6 6 6 7 7];
B = [6 6 6 7 7 7 7 7 7 7 8 8 8 9 9 10 10];
hist(A,7);
hold on
hist(B,7);
h = findobj(gca,'Type','patch');
set(h(1),'FaceColor','b','EdgeColor','b','facealpha',0.2)
set(h(2),'FaceColor','r','EdgeColor','r','facealpha',0.2)
xlabel('Day','fontsize',14)
ylabel('Frequency','fontsize',14)
xlim([1 10])
Now say I have these data:
Day = [1 2 3 4 5 6 7 8 9 10];
Prevalence = [3 2 4 8 5 6 7 8 9 5];
I want to plot these data (plot(Day,Prevalence)) using the right y-axis.
Thanks.
I think this workaround will do what you want.
Basically create a new axes at the same position than the one in which the histograms are plot, however set its color property to 'none' and the YAxisLocation to the right. You can then assign the new axes the properties you want.
Code:
clear
clc
%// ====================
%// Your code
A = [1 2 2 2 3 4 5 5 5 5 5 5 5 5 5 6 6 6 7 7];
B = [6 6 6 7 7 7 7 7 7 7 8 8 8 9 9 10 10];
hist(A,7);
hold on
hist(B,7);
h = findobj(gca,'Type','patch');
set(h(1),'FaceColor','b','EdgeColor','b','facealpha',0.2)
set(h(2),'FaceColor','r','EdgeColor','r','facealpha',0.2)
xlabel('Day','fontsize',14)
ylabel('Frequency','fontsize',14)
xlim([1 10])
%// ====================
Day = [1 2 3 4 5 6 7 8 9 10];
Prevalence = [3 2 4 8 5 6 7 8 9 5];
%// Get the current axes position to place the new one.
AxesPos = get(gca,'Position');
hold on
hax2 = axes('Position',AxesPos);
%// Plot the data
plot(Day,Prevalence,'--k','LineWidth',4,'Parent',hax2)
%// Set properties of the axes.
set(hax2,'Color','none','YAxisLocation','right','XTick',[],'XTickLabel','','YLim',[0 15])
ylabel('Prevalence','FontSize',16)
%// Rotate the label to correct orientation
LabelPos = get(get(hax2,'YLabel'),'Position');
set(get(hax2,'YLabel'),'Position',[LabelPos(1)+.2 LabelPos(2) LabelPos(3)],'Rotation',-90)
Output:
Note that it's far from perfect ...for example the left border of the first axes is not visible...that could be fixed by playing around with the position of the new axes. Hopefully it does the job for you!

matlab colormap with three columns

I want to draw a color map with three columns in matlab.
I can draw with plot3 like below,
x = [1 1 1 1 2 2 2 2 4 4 4 4 5 5 5 5 9 9 9 9];
y = [2 3 4 5 5 6 7 8 4 5 6 7 1 2 3 4 7 8 9 10];
z = [1 3 2 4 5 6 7 3 9 8 8 9 2 4 3 5 1 2 3 1];
plot3(x, y, z, 'o')
But how can I draw 2D color map with three columns?
Option 1:
If I understand you correctly you want to draw a 2D array (say m(x,y)) where the color is given by z. this is how:
m=zeros(max(x),max(y)); % preallocate m according to values of x,y
m(sub2ind(size(m),x,y))=z; % assign z-values to the x,y coordinates
imagesc(m) % plot
colormap(pink(max(z))); % set colormap with the dynamic range of z.
% you can replace it with jet or whatever...
colorbar % add a colorbar
Option 2:
you really just want to create am RGB colormap from x,y,z:
cmap=[x(:) y(:) z(:)]./max([x(:);y(:);z(:)]);
imagesc(peaks(100));
colormap(cmap);

plot elements of array with different colors

I have a vector of integers that vary from 1 to 4.
A=[1 2 3 4 2 3 2 1 2 3 4 4]
I would like to plot A with different colors for each value...
the vertical line that links A(1) to A(2) should have the color of the first value (in this case 1).
Is that possible?
and how to handle the case of NaN present in the vector?
I should plot A against a time vector
A = [1 1 1 NaN 4 4 4 Nan 2 2 3 3];
time = [1 2 3 4 5 6 7 8 9 10 11 12];
Suppose you have the following set of colors:
col = hsv(4);
You set the order of the colors based on the values of A:
figure();
set(gca, 'ColorOrder', col(A,:), 'NextPlot', 'replacechildren');
Then, you can plot each line in the desired color:
n = numel(A);
plot(hankel(0:1,1:n-1),hankel(A(1:2),A(2:n)))
This results in:
Edit:
The hankel approach is a bit like shooting with a bazooka to kill a mosquito, as we say in the Netherlands. Anyway, I learned about it a few questions ago - so I liked to use it. See the post of Dan for a simpler alternative for the plotting. Still, setting the correct colors can be done as in the above.
You can do it using just a touch of trickery:
A=[1 2 3 4 2 3 2 1 2 3 4 4]
x = [1:numel(A)-1; 2:numel(A)];
y = A(x);
plot(x,y)

Group matrix values into separate matrices based on values of another matrix

I am reading in images with imread which results in 768x1024x3 matrix with R,G,B values of each pixel.
I have a function that takes in an image and returns matrix of segment labels for each pixel so this matrix is 768x1024. the labels are just numbers 1,2,3,4 depending on how many different segments the function finds.
Now I want to calculate the average Red, Green and Blue value in each segment of the image. So I want to use the indices from the segment label matrix to find group all R,G,B values into separate arrays and then be able to calculate the mean.
Is there any smart way to do this? use the indices of each 1 value in the segment matrix to get the values from the imread matrix and group the segments into different arrays? I though of using for loops and brute force through this but is there a better way to do this?
Here's a code that you will get you everything without looping.
Code
%// img is your input RGB image (NxMx3)
%// L is your label matrix (NxM)
t1 = bsxfun(#eq,L,permute(unique(L),[3 2 1]));
t2 = bsxfun(#times,permute(img,[ 1 2 4 3]),t1);
t2(t2==0)=nan;
out = squeeze(nanmean(nanmean(t2)))
%// out is the desired output matrix that is (NLx3),
%// where NL is the number of labels. Thus, the mean of labels is
%// along the rows and the corresponding values for R, G and B are in the three
%// columns of it.
Explanation
Let's test out with some random values for img -
img = randi(9,3,4,3)
Giving us -
img(:,:,1) =
9 7 5 3
7 7 2 4
1 6 7 9
img(:,:,2) =
8 6 6 4
4 9 3 9
3 9 8 1
img(:,:,3) =
5 4 4 5
7 2 5 3
2 3 1 3
Some assumed values for L that goes from 1 to 8
L = [1 3 3 4;
4 5 8 8;
5 6 7 2]
The code output is -
out =
9 8 5
9 1 3
6 6 4
5 4 6
4 6 2
6 9 3
7 8 1
3 6 4
Let's see how to make sense of the output.
Looking at the input, let's choose the label 8, which is at locations (2nd row,3rd col) and (2nd row,4th col). The corresponding R values at these locations in img are [2 4], and thus the R mean/average value must be 3. Similarly for G it must be from [3 9], that is 6 and again for B would be from [5 3], that is 4.
Let's look at the 8th row of out that represents the label-8, we have [3 6 4], which are the mean values as calculated earlier. Similarly other mean values could be interpreted from out.
Edited to handle all channels at once.
Let img be your RGB image and labels the labels array.
You can mask the RGB image with the labels like this:
% create a 3-channels mask:
labelsRGB=repmat(labels, 1, 1, 3);
Segment1=img.*(labelsRGB==1);
The average values in the segment labeled as 1 is then:
avg=mean(mean(Segment1, 1), 2);
Get the average for re in avg(1), the average for green in avg(2), etc.
Idem for the other segments.
Here goes a general alternative.
In this case you do not need to loop over the different segments to get the average of each.
%simulated image and label
img=rand(10,12,3);
labeled=[ones(10,3),ones(10,3)*2,ones(10,3)*3,ones(10,3)*4];
% actual code for the mean
red_mean = regionprops(labeled, img(:,:,1), 'MeanIntensity')