How to display two overlapping lines in matlab - matlab

I have to plot 5 lines that overlap in some regions, and I need to be able to see all the lines.
I can think of shifting the lines a bit to allow them to be displayed, but this doesn't seem a very elegante solution. Even so, how could I code such a thing?
Is there any other way to plot multiple overlapping lines while being able to distinguish them at every point?
For exemple, here is one exemple with 3 overlapping lines:
Thank you in advance!

Another way is to use transparency.
Unfortunatelly, line objects do not obey
transparency commands :(
A workaround is to:
1. download patchline (<-- link to Matlab Central)
2. use it to plot patchline with transparency
Once you have patchline, you can try something like:
% create some lines:
l1 = [1, 1, 1, 0, 0, 0.25, 1, 1, 0, 0, 0, 0, 1 1];
l2 = [0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1];
l3 = [1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0];
% plot with patchline (notice the use of 'EdgeAlpha'):
figure;
patchline(1:length(l1), l1, [], 'EdgeColor', [0.8, 0.2, 0.35],...
'LineWidth', 5, 'EdgeAlpha', 0.5 );
hold on;
patchline(1:length(l1), l2, 'EdgeColor', [0.2, 0.7, 0.55],...
'LineWidth', 5, 'EdgeAlpha', 0.5 );
patchline(1:length(l1), l3, 'EdgeColor', [0.1, 0.2, 0.95],...
'LineWidth', 5, 'EdgeAlpha', 0.5);
% change y limits to see line overlap clearly
set(gca, 'YLim', [-0.5, 1.5]);
Not an ideal way to do it - the rough 'cracks' will stay this way,
but you can experiment with different line widths or moving the
lines in y axis by a value that would correspond to an image with each
line covering only half of it closest neighbour...

You may play with EraseMode property of the plot line. The following code example shows how to shift the lines and EraseMode effect:
% First we generate some data
NLines = 2;
NPoints = 50;
LineWidth = 3;
ShiftStep = 1.1;
XData = linspace(0,1,NPoints);
YData = rand(NPoints,NLines);
for k=1:NLines
YData(:,k) = YData(:,k) > (k/(NLines+1));
end
% Then we create plot
figure('color','w');
subplot(3,1,1); plot(XData,YData, 'LineWidth',LineWidth);
ylim([-0.1 1.1]);
title('simple')
subplot(3,1,2); plot(XData,YData+repmat((0:NLines-1)*ShiftStep,NPoints,1), 'LineWidth',LineWidth, 'EraseMode','xor');
ylim([-0.1 1.1+ShiftStep*(NLines-1)]);
title('Shifted vertically')
subplot(3,1,3); plot(XData,YData, 'LineWidth',LineWidth, 'EraseMode','xor');
ylim([-0.1 1.1]);
title('EraseMode = xor')
In my opinion if you have more than three lines similar to your plot, shifting is visually more attractive. Also you may create several axes (Like I did) and plot each line in its own axes, so they will have y-labels set accordingly, but their X-labels will be essentially the same.

You can use plot3 and assign different Z values to different overlapping lines. However, it'll look more like you expect (Z being the "up" direction) if you swap the Y and Z axes:
Example:
Y1 = randn(1,100);
Y2 = randn(1,100);
X = 1:100;
Z1 = 1*ones(size(X));
Z2 = 2*ones(size(X));
plot3(X,Z1,Y1);
hold on;
plot3(X,Z2,Y2);

Related

How can I create a rectangle with a hole in MATLAB/OCTAVE?

I would like to plot/draw exactly this shape in MATLAB or OCTAVE. Of course I do know how to plot, and how to create rectangles, using either the plot, the line or the rectangle functions. But I have not yet managed to add this "hole" on the top side of the rectangle. I figure, it's a (half-)circle of radius 0.5 and center point (1.5|2). In OCTAVE, there is a drawCircleArc function, but I don't want to only draw that thing, but also to have the necessary coordinates defining the whole shape for further manipulation.
Here is one way (matlab/octave compatible):
% Specify all polygon points, excluding the semi-circle outline
X = [1, 0, 0, 3, 3, 2];
Y = [2, 2, 0, 0, 2, 2];
% Add semi-circle outline to array of polygon points
t = 0 : -0.01 : -pi;
X = [X, 1.5 + 0.5 * cos(t)];
Y = [Y, 2 + 0.5 * sin(t)];
% Use fill to plot the filled polygon, with desired settings
fill( X, Y, [0.8, 0.8, 0.8], 'linewidth', 1.5 );
axis( [-2, 4, -2, 4] ); axis equal;
As of 2017b you can also use polyshapes and boolean operators.
rect = polyshape([0 3 3 0], [0 0 2 2]);
t = linspace(0, 2*pi, 32);
circ = polyshape(1.5+.5*cos(t), 2+.5*sin(t));
subplot 121, hold on
plot(rect)
plot(circ)
axis equal
shape = subtract(rect, circ);
subplot 122
plot(shape)
axis equal

How can I add vertical lines to my confusion matrix generated with matlab?

I have used the following code to generate my confusion matrix, which I have found it on internet :
confmat = C;
labels = {'0', '1', '2', '3', '11' };
numlabels = size(confmat, 1); % number of labels
confpercent = 100*confmat./repmat(sum(confmat, 1),numlabels,1);
imagesc(confpercent);
Mycolors=[0 0.7 0.4; 1 0.9 0.9 ]
colormap(flipud(Mycolors));
textStrings = num2str([confpercent(:)], '%.1f%%\n');
textStrings = strtrim(cellstr(textStrings));
[x,y] = meshgrid(1:numlabels);
hStrings = text(x(:),y(:),textStrings(:), ...
'HorizontalAlignment','center');
midValue = mean(get(gca,'CLim'));
textColors = repmat(confpercent(:) > midValue,1,3);
set(hStrings,{'Color'},num2cell(textColors,2));
set(gca,'XTick',1:numlabels,... 'XTickLabel',labels,... 'YTick',1:numlabels,... 'YTickLabel',labels,... 'TickLength',[0 0]);
I have gotten the next matrix
While I want to add vertical lines to my matrix to separate between values so I can get a similar one to the next :
I could get those vertical lines using pcolor(confusion_matrix) but the percentages are shiffted to the corner of each grid and I have got the next picture :
Use another axes object
The classic MATLAB trick when having to deal with different axes properties.
Basically we are going to create a new axes object, place it on top of the precious one, then make it transparent (no background color) so we can see what's behind, but we'll keep the grid lines well visible right where we want them.
So immediately after your sample code, add:
ax1 = gca ; % get handle of initial axes
ax2 = axes ; % create new axe and retrieve handle
lim = [0 numlabels] ; % Prepare X and Y properties
tks = 0:numlabels ;
% superpose the new axe on top, at the same position
set(ax2,'Position', get(ax1,'Position') );
% make it transparent (no color)
set(ax2,'Color','none') ;
% set the X and Y properties
set(ax2, ...
'XLim',lim,'XTick',tks,'XTickLabel','' ,...
'YLim',lim,'YTick',tks,'YTickLabel','' ) ;
% now set your grid properties
set(ax2,'GridColor','k','GridAlpha',1)
This will get you (data differ a bit because I randomly generated the confusion matrix):
Of course now you have full control over your grid lines, so you can also refine how they appear through the grid properties of the axes. A few interesting properties are:
GridLineStyle — Line style for grid lines
GridColor — Color of grid lines
GridAlpha — Grid-line transparency
LineWidth — Line width
For more details, look at the documentation for Axes Properties
Well !
I have found the requested thing to get the vertical and horizantal line, which is adding the lines simply using plot and hold on :
I have used the next code at the end of the mentioned one in my question :
hold on
plot ([2 2],get(gca, 'YLim'), 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot ([1 1],get(gca, 'YLim'), 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot ([3 3],get(gca, 'YLim'), 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot ([4 4],get(gca, 'YLim'), 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot (get(gca, 'XLim'), [1 1], 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot (get(gca, 'XLim'), [2 2], 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot (get(gca, 'XLim'), [3 3], 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
plot (get(gca, 'XLim'), [4 4], 'Color', [0.15, 0.15, 0.15],'LineWidth',0.5)
I have used 1, 2, 3 and 4 because I have four classes and at the end of each class prediction results I need to plot the line.
Hope that will be useful

Hatched bars and standard deviation errors in bar charts with Matlab

I'm trying to create a bar plot. On the x axis I have 4 different conditions: HFd, HFi, LFd, LFi. On the y axis Reaction time is displayed.
I need the bar representing HFd to be hatched and blue, HFi to be blue, LFd to be hatched and red, LFi to be red. In addition, I need the standard deviation to be displayed in black on each bar.
Here are my attempts. Although they work, they don't give me the bar plot I need. Any help would be very much appreciated.
%% This code creates the plot, but without the standard deviation errors
and the different colours.
data1 = [228, 222, 229, 218];
sdev1 = [29, 30, 29, 31];
hold on;
figure;
bar(data1);
%errorbar(data1, sdev1); %it gives me a line that links the different standard deviation errors.
set(gca, 'XTickLabel',{'HFd', 'HFi', 'LFd', 'LFi'});
ylabel('Reaction time (ms)');
ylim([180 300]);
%% This code creates the plot, with different colours but without the hatched
patterns and the standard deviation errors.
dataHFdeg = [228, 0, 0, 0];
sdev11 = [29, 0, 0, 0]
dataHFid = [0, 222, 0, 0];
sdev12 = [0, 30, 0, 0]
dataLFdeg = [0, 0, 229, 0];
sdev13 = [0, 0, 29, 0]
dataLFid = [0, 0, 0, 218];
sdev14 = [0, 0, 0, 31]
bar(dataHFd,'b');
set(gca, 'XTickLabel',{'HFd', 'HFi', 'LFd', 'LFi'});
ylabel('Reaction time (ms)');
ylim([180 300]);
hold on;
bar(dataHFi, 'b');
hold on;
bar(dataLFd, 'r');
hold on;
bar(dataLFi, 'r');
UPDATE:
%% This code creates the plot, with different colours and with error bars, but without the hatched patterns
y = [228; 222; 229;218]; %The data.
s = [29;30;29;31]; %The standard deviation.
fHand = figure;
aHand = axes('parent', fHand);
hold(aHand, 'on')
bar(1, y(1), 'parent', aHand, 'facecolor', 'b');
bar(2, y(2), 'parent', aHand, 'facecolor', 'b');
bar(3, y(3), 'parent', aHand, 'facecolor', 'r');
bar(4, y(4), 'parent', aHand, 'facecolor', 'r');
colors = copper(numel(y) - 4);
for i = 5:numel(y)
bar(i, y(i), 'parent', aHand, 'facecolor', colors(i-4,:));
end
set(gca, 'XTick', 1:numel(y), 'XTickLabel', {'HFd','HFi','LFd','LFi'})
ylim([180 300]);
errorbar(y,s,'.');
%% To create for example the hatched pattern for the second bar - but it doesn't work
applyhatch_pluscolor(bar(2,y(2)), '/', 1);

How do I modify the legend in a Matlab plot?

I would like to draw four circles of two colors. I'm using circle function to draw a circle. I'm facing problem with legend(). It colors the two data with the same color.
function main
clear all
clc
circle([ 10, 0], 3, 'b')
circle([-10, 0], 3, 'b')
circle([ 10, 10], 3, 'r')
circle([-10, 10], 3, 'r')
% Nested function to draw a circle
function circle(center,radius, color)
axis([-20, 20, -20 20])
hold on;
angle = 0:0.1:2*pi;
grid on
x = center(1) + radius*cos(angle);
y = center(2) + radius*sin(angle);
plot(x,y, color, 'LineWidth', 2);
xlabel('x-axis');
ylabel('y-axis');
title('Est vs Tr')
legend('true','estimated');
end
end
The following picture shows the problem. Both colored as blue instead one of them is red.
Any suggestions?
You can make your function circle() return the plot handles. Store the handles in a vector. In the end, you only call legend() once, after plotting all circles. The first argument in legend are then the function handles which you want to appear in the legend. Something like this:
function main
% clear all % functions have their own workspace, this should always be empty anyway
clc
handles = NaN(1,2);
handles(1,1) = circle([ 10, 0], 3, 'b'); % handle of a blue circle
circle([-10, 0], 3, 'b')
handles(1,2) = circle([ 10, 10], 3, 'r'); % handle of a red circle
circle([-10, 10], 3, 'r')
% Nested function to draw a circle
function h = circle(center,radius, color) % now returns plot handle
axis([-20, 20, -20 20])
hold on;
angle = 0:0.1:2*pi;
grid on
x = center(1) + radius*cos(angle);
y = center(2) + radius*sin(angle);
h = plot(x,y, color, 'LineWidth', 2);
xlabel('x-axis');
ylabel('y-axis');
title('Est vs Tr')
end
% legend outside of the function
legend(handles, 'true','estimated'); % legend for a blue and a red circle handle
end
The result looks like this:
The thing is that you draw 4 things and only have 2 entries in the legend.
As such it will pick the color of the first four things to color the legend.
Not in the opportunity to try it myself now, but I guess that the easiest 'solution' would be to draw your third circle first and then the second one.
circle([ 10, 0], 3, 'b')
circle([ 10, 10], 3, 'r')
circle([-10, 0], 3, 'b')
circle([-10, 10], 3, 'r')

Plotting a line above/below existing lines created with plotyy

I'm running this code:
t = linspace(0, 10, 1000);
y1 = 2*t;
y2 = 3*t;
figure;
[ax, h1, h2] = plotyy(t, y1, t, y2);
set(h1, 'LineWidth', 4);
set(h2, 'LineWidth', 4);
hold on;
h3 = plot([5, 5], [0, 3000], 'LineWidth', 6, 'Color', [0.6, 0.6, 0.6]);
Which creates this plot:
Notice how the vertical grey line appears on top of the blue line (y1) but below the green line (y2).
How do I plot the grey line either on top of the other two lines, or below the other two lines?
I see two options:
A. Bring the gray line forward by moving it to the second axes created by the plotyy command
set(h3,'parent',ax(2));
B. Place the gray line on the bottom by rearranging the order of the blue and grey lines on
the axes.
chld = [h1 h3];
set(ax(1),'children',chld); %# reorders the two lines so that the gray line is in back.
To make the gray line bottom, you can also change the order of drawing.
t = linspace(0, 10, 1000);
y1 = 2*t;
y2 = 3*t;
figure;
h3 = plot([5, 5], [0, max(y1)], 'LineWidth', 6, 'Color', [0.6, 0.6, 0.6]);
hold on;
[ax, h1, h2] = plotyy(t, y1, t, y2);
set(h1, 'LineWidth', 4);
set(h2, 'LineWidth', 4);
There's a trick in h3 = plot(...) to make sure the left scale is correct, though.