Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotting with a Specific Marker

I would like to plot a matrix of zeros and ones into a figure such that for every 1 i have a marker shaped like a vertical bar is plotted " | ". Such that when a series of 1s are on the same x axis, the look like a long straight line.

This example illustrates my intentions:

Given the following matrix:

0 0 1 1 0 1 0
0 1 0 1 1 1 0
0 1 0 1 1 1 0
1 0 0 1 1 1 0

I get:

Bar Figure

like image 694
alandalusi Avatar asked Jun 25 '11 18:06

alandalusi


3 Answers

EDIT:

The solution below, although a bit longer than the currently accepted one, has the advantage that it creates a single LINE object (UI performance is better if you create fewer graphics objects). It works by using NaN to separate the segments:

%#A = [1 1 1 ; 0 0 0 ; 1 1 1];
A = [
    0 0 1 1 0 1 0
    0 1 0 1 1 1 0
    0 1 0 1 1 1 0
    1 0 0 1 1 1 0
];

%# build line x/y points
[m n] = size(A);
[x y] = meshgrid(1:n, 1:m);    %# grid coordinates
x(~A) = NaN;                   %# place NaNs where A is zero
y(~A) = NaN;
x = [x;NaN(1,n)];              %# separate columns by NaNs
y = [y;NaN(1,n)];
x = [x(:) x(:)]';              %'# add endpoints
y = [y(:) y(:)+1]';            %'#
x = x(:);                      %# linearize
y = y(:);

%# plot
line('XData',x, 'YData',y-0.5, 'Color','k', 'LineStyle','-', 'LineWidth',4)
set(gca, 'XGrid','on', 'Box','on', 'FontSize',8, 'LineWidth',2, ...
    'XLim',[0 n]+0.5, 'YLim',[0 m]+0.5, 'XTick',1:n, 'YTick',1:m, ...
    'YDir','reverse')
%#set(gca, 'XTick',[], 'YTick',[])

enter image description hereenter image description here

like image 112
Amro Avatar answered Oct 08 '22 18:10

Amro


SOLUTION 2

Here is another solution, which looks quite simple. Each number represented by a single vertical line. All in one plot statement.

%# create the matrix and get coordinates of 1s.
a = logical([
0 0 1 1 0 1 0
0 1 0 1 1 1 0
0 1 0 1 1 1 0
1 0 0 1 1 1 0]);
[r c] = find(flipud(a));
plot([c c]',[r-0.5 r+0.5]','k-')
xlim([min(c)-0.5 max(c)+0.5])
set(gca,'xtick',[],'ytick',[])
box on

enter image description here


SOLUTION 1

As an alternative you can use TEXT function to place '|' symbol at certain coordinates.

[r c] = find(flipud(a));
clf
text(c,r,repmat('|',numel(r),1),'FontSize',70,'hor','center','vert','middle')
xlim([min(c)-0.5 max(c)+0.5])
ylim([min(r)-0.6 max(r)+0.4])
set(gca,'xtick',[],'ytick',[])
box on

The drawback is that you have to play with the font size and y axis limits to close the lines.

enter image description here

Side note: It's weird, that I couldn't use just '|' without repmat. Because this character can actually separate different strings. Using char(124) has the same effect. I wonder if there is any other workaround.

like image 40
yuk Avatar answered Oct 08 '22 20:10

yuk


Here is one way of doing it by converting the 1's to explicit points and drawing a line through them:

B=logical([A(1,:);A;A(end,:)]);    %# A is your matrix of 1's and 0's

%# create a mesh of indices
x=1:size(B,2);
y=0:size(A,1)+1;
[X,Y]=meshgrid(x,y);

%# plot the lines
figure(1);clf;hold on
arrayfun(@(i)plot(X(B(:,i),i)',Y(B(:,i),i)','color','k','linewidth',1.25),x)
hold off 
set(gca,'box','on','xlim',[min(x),max(x)]+[-1/2 1/2],...
'ydir','r','ytick',[])

Here is what you should get:

enter image description here

You can probably do away with the arrayfun, but I'll leave that to you if you so wish.

like image 45
abcd Avatar answered Oct 08 '22 19:10

abcd