How to plot discrete array with colors
20 views (last 30 days)
Show older comments
I have 'nodes' which each have a status. The status of these nodes are contained in an array 'status_array' and have the values "waiting" or "busy". I would like to plot an array with colors indicating what state each node is in, for example, green = 'waiting' and red = 'busy'. This way I can visualize how the node transistion from their states. I want it to look something like this:
I tried using imagesc or bar but it doesn't look quite right.
Thanks in advance for any suggestions!
0 Comments
Answers (3)
Star Strider
on 20 Jun 2023
One approach —
status = randi([0 1], 1, 9) % 'Waiting' = 0, 'Busy' = 1
status = flip(status);
cv = ["g" "r"]; % Coluur Vector
xv = repmat([0 1], size(status,2), size(status,1));
yv = xv + (0:size(status,2)-1).';
figure
% patch([xv fliplr(xv)], [yv fliplr(yv)], cv(status+1))
hold on
for k = 1:numel(status)
patch([xv(k,:) fliplr(xv(k,:))], [[1 1]*yv(k,1) [1 1]*(yv(k,2))], cv(status(k)+1))
end
hold off
xlim([0 0.1])
% axis('equal')
daspect([0.1 1 1])
xticks([])
yt = yticks;
yticks(0.5:max(yt))
yticklabels(yt(2:end))
I could not get this to work correctly without the loop.
.
1 Comment
dpb
on 20 Jun 2023
Edited: dpb
on 20 Jun 2023
I didn't go back to the beginning to try to remove the loop there, but it's not terribly difficult to then update the graphic to match a new status vector without looping...
Following copies the above with one exception during creation -- save a vector of patch handles, hP, to use to address the objects later.
status = randi([0 1], 1, 9) % 'Waiting' = 0, 'Busy' = 1
status = flip(status);
cv = ["g" "r"]; % Coluur Vector
xv = repmat([0 1], size(status,2), size(status,1));
yv = xv + (0:size(status,2)-1).';
figure
hold on
hP=gobjects(size(status)); % patch handles array
for k = 1:numel(status)
hP(k)=patch([xv(k,:) fliplr(xv(k,:))], [[1 1]*yv(k,1) [1 1]*(yv(k,2))], cv(status(k)+1));
end
hold off
xlim([0 0.1])
daspect([0.1 1 1])
xticks([])
yt = yticks;
yticks(0.5:max(yt))
yticklabels(yt(2:end))
Above ends the original iwth the one mod noted...now update given a new status...but, the .FaceColor property is actually an RGB triplet; the patch() function will accept the shortnames for the base colors but have to use rgb to set directly...
% define the rgb triplets to go with the original colors
R=[1 0 0]; G=[0 1 0]; CV=[G;R]; % lookup vector to match "g","r"
status = randi([0 1], 1, 9); % a new status vector
status=flip(status); % match order to object handle order
cv(status+1) % what what it is for comparison in string form
set(hP,{'FaceColor'},num2cell(CV(status+1,:),2)) % update the colors to match
Remember to look at the colors in comparison to the color names from bottom up, not top down!!! :)
Askic V
on 20 Jun 2023
I would also like to offer my solution. It is not so elegant comparing to @Star Strider, but it can show you how bar can be used to achieve something similar:
clear;clc;close all;
red = [1 0 0];
green = [0 1 0];
% Example data
data = [1; 0; 1; 0; 0; 1; 1; 0; 1];
% Adjust the width of the bars
barWidth = 0.8; % Specify the desired width of the bars
barWidthRatio = barWidth / numel(data); % Calculate the ratio of the desired width to the number of bars
h = bar(1, ones(size(data, 1), 1), 'stacked');
for i = 1:numel(data)
h(i).BarWidth = barWidthRatio;
if data(i) == 1
h(i).FaceColor = green;
else
h(i).FaceColor = red;
end
text(0.95, i, num2str(i), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
end
axis ij; % invert axis
ylabel('Value');
ylim([0 size(data, 1)+1]);
yticks(1:size(data, 1)); % Set the y-axis tick locations
yticklabels([]); % Hide the y-axis tick labels
0 Comments
dpb
on 20 Jun 2023
Edited: dpb
on 21 Jun 2023
I looked at the vectorized version issue a little -- it doesn't work easily for the purpose because even if you create multiple polygons, it's then a one-object patch with only a single .FaceColor property. To set the colors by face then have to set the initial color vector as a nx1x3 rgb array which is more of a pain to generate than the lookup of the color vector or 2D array.
While doable and does create the same overall effect, I think it's handier to leave it as the separate patch objects above -- although I guess once one writes the code once, even if it was harder initially, then it doesn't really matter to use...
The following works...
status=randi(2,[1,9])-1;
status=flip(status);
status
x=[0 1 1 0].'; y=[0 0 1 1].';
x=repmat(x,size(status));
y=repmat(y,size(status))+[0:numel(status)-1];
G=[0 1 0];G=reshape(G,1,1,[]);
R=[1 0 0];R=reshape(R,1,1,[]);
C=[G; R];
c=C(status+1,1,:);
hP=patch(x,y,c);
box on
xlim([0 0.1])
daspect([0.1 1 1])
prior to the cleanup of tick labels, etc., ...
0 Comments
See Also
Categories
Find more on Polygons in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!