plot elements of array with different colors - matlab

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)

Related

Reshape a matrix by splitting it after k columns in MATLAB

Suppose that I have a matrix , let's call it A, as follows:
1 2 3 4 5 1 2 3 4 5
0 2 4 6 8 1 3 5 7 9
And I want to reshape it into a matrix like this:
1 2 3 4 5
0 2 4 6 8
1 2 3 4 5
1 3 5 7 9
So, basically, what I want to be done is that MATLAB first reads a block of size (2,5) and then splits the remaining matrix to the next row and then repeats this so on so forth until we get something like in my example.
I tried to do this using MATLAB's reshape command in several ways but I failed. Any help is appreciated. In case that it matters, my original data is larger. It's (2,1080). Thanks.
I don't believe you can do this in a single command, but perhaps someone will correct me. If speed isn't a huge concern a for loop should work fine.
Alternatively you can get your results by reshaping each row of A and then placing the results into every other row of a new matrix. This will also work with your larger data.
A = [1 2 3 4 5 1 2 3 4 5
0 2 4 6 8 1 3 5 7 9];
An = zeros(numel(A)/5, 5); % Set up new, empty matrix
An(1:2:end,:) = reshape(A(1,:), 5, [])'; % Write the first row of A to every other row of An
An(2:2:end,:) = reshape(A(2,:), 5, [])' % Write second row of A to remaining rows
An =
1 2 3 4 5
0 2 4 6 8
1 2 3 4 5
1 3 5 7 9
You may need to read more about indexing in the Matlab's documentation.
For your example, it is easy to do the following
A=[1 2 3 4 5 1 2 3 4 5; 0 2 4 6 8 1 3 5 7 9]
a1=A(:,1:5); % extract all rows, and columns from 1 to 5
a2=A(:,6:end); % extract all rows, and columns from 6 to end
B=[a1;a2] % construct a new matrix.
It is not difficult to build some sort of loops to extract the rest.
Here's a way you can do it in one line using the reshape and permute commands:
B = reshape(permute(reshape(A,2,5,[]), [1,3,2]), [], 5);
The reshape(A,2,5,[]) command reshapes your A matrix into a three-dimensional tensor of dimension 2 x 5 x nblocks, where nblocks is the number of blocks in A in the horizontal direction. The permute command then swaps the 2nd and 3rd dimensions of this 3D tensor, so that it becomes a 2 x nblocks x 5 tensor. The final reshape command then transforms the 3D tensor into a matrix of dimension (2*nblocks) x 5.
Looking at the results at each stage may give you a better idea of what's happening.

How can I plot part of a simple vector?

Suppose I've got the following vector and plot it from index 1 to 11:
a = [1 2 5 4 5 4 2 3 7 1 5];
plot(a);
How can I plot only part of this vector? like from index 3 to index 7. I found this question but couldn't figure out how to use it.
a = [1 2 5 4 5 4 2 3 7 1 5];
plot(a(3:7));

Matlab adjusting heat map axes and colors

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)))

matlab plot jump discontinuity [duplicate]

This question already has an answer here:
Plotting a Continuous signal
(1 answer)
Closed 8 years ago.
Is it possible to plot a sequence of data without interpolating them?
I would like to keep the value of one data point until the value of the next one.
So for example:
I have my time vector
time = [1 2 3 4 5 6]
and datapoints =[3 0 1 4 5 6]
I would like that the line of my plot is 3 from time(1) till time(2) and then it should change in time(2) to take the value 0.
Basically in correspondence of the time 2 my plot should assume both the value 3 and 0 (jump discontinuity)...
I hope I was clear.
A short answer: yes you can.
Use the stairs() function.
time=[1 2 3 4 5 6];
datapoints = [3 0 1 4 5 6];
stairs(time,datapoints)
Good luck!
you have to duplicate the times as well the datapoints and plot them shifted in order to get the staircase-style:
time = [1 2 3 4 5 6];
datapoints =[3 0 1 4 5 6];
datapoints = [datapoints, datapoints];
[time, idx] = sort([time, time]);
time(1) = [];
datapoints = datapoints(idx);
datapoints(end) = [];
plot(time,datapoints)

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')