plotting a curve in MATLAB with prefefined x-axis - matlab

I have two vectors:
x = [1, 2, 3, 5, 6, 10, 20, 50, 100]
and
y=[7, 1, 2, 4, 2, 1, 5, 1, 1];
I am interested to plot Y as a function of X in MATLAB. So, this can be done by:
figure;
plot(x, y, '--rs');
In fact, the code above plots the curve, but the x-axis seems to be spaced as follows: 0, 10, 20, ..., 100.
What I want is to draw a curve which exhibits just the values in x as x-axis and their corresponding y-axis values. An example of x-axis is shown in the picture below.
Any help will be very appreciated!!

Instead of plotting using plot(x,y), use plot(1:numel(x),y) and use the XTick and XTickLabels` properties to change the labelling of the graph to suit your need.
Example:
clc
clear
x = [1, 2, 3, 5, 6, 10, 20, 50, 100];
y=[7, 1, 2, 4, 2, 1, 5, 1, 1];
plot(1:numel(x),y,'--rs')
set(gca, 'XTick', 1:length(x)); %// Change x-axis ticks
set(gca, 'XTickLabel', x); %// Change x-axis ticks labels.
Result:
Hope that helps!

Related

Using Matlab to get maximum values from many polyfitted curves in one figure

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
z1 = [1, 4, 9, 16, 25, 36, 49, 36, 25, 16, 8, 1];
z2 = [1, 5, 10, 17, 26, 38, 26, 17, 10, 9, 7, 1];
z3 = [1, 8, 18, 30, 40, 30, 18, 8, 7, 4, 3, 1];
plot(x, z1, '*');
hold on;
p1 = polyfit(x, z1, 5);
z1fit = polyval(p1, x);
plot(x, z1fit);
hold on;
plot(x, z2, '*');
p2 = polyfit(x, z2, 5);
z2fit = polyval(p2, x);
plot(x, z2fit);
hold on;
plot(x, z3,'*');
p3 = polyfit(x, z3, 5);
z3fit = polyval(p3, x);
plot(x, z3fit);
My question is, how to find every maximum value of each curve and display them? The maximum points are not the maximum values that I gave , It should be the peak points after fitting. I can simply read these peak points from the plotted figure, just want to know how to get the exact coordinate of the highest peak of the polynomial fit and return them. The degree of n (in my code 5) from polyfit is changeable.
To get the exact value of the maximum in the range of x, you can use the optimization toolbox.
x=[1,2,3,4,5,6,7,8,9,10,11,12];
z1=[1,4,9,16,25,36,49,36,25,16,8,1];
p1=polyfit(x, z1, 5);
fun = #(x) -polyval(p1,x);
x_max = fminbnd(fun,x(1),x(end))
figure; hold on;
plot(x,z1,'*');
fplot(#(x) polyval(p1,x),[x(1) x(end)],':');
plot(x_max,polyval(p1,x_max),'o');
legend('data','fit','max')
Use the polyfit function to get the coefficients of the fitted polynomial, use the polyval function to create a function handle to the polynomial you created and the fminbnd to "Find minimum of single-variable function on fixed interval". With the function handle, you can use the fplot function to plot the fit.
Edit:
If you want to calculate and plot the fitted curves in the same figure, you can:
x=[1,2,3,4,5,6,7,8,9,10,11,12];
z1 = [1, 4, 9, 16, 25, 36, 49, 36, 25, 16, 8, 1];
z2 = [1, 5, 10, 17, 26, 38, 26, 17, 10, 9, 7, 1];
z3 = [1, 8, 18, 30, 40, 30, 18, 8, 7, 4, 3, 1];
z = [z1;z2;z3];
figure; hold on;
for ii=1:size(z,1)
p1=polyfit(x, z(ii,:), 5);
fun = #(x) -polyval(p1,x);
x_max = fminbnd(fun,x(1),x(end))
plot(x,z(ii,:),'*');
fplot(#(x) polyval(p1,x),[x(1) x(end)],':');
plot(x_max,polyval(p1,x_max),'o');
end
The result, however, will not be that good, because you will have a lot of information in the same figure. Depending on what you want, that may be good. But I suggest you plot on different figures different data, maybe using subplots.

Matlab extends graph in EPS export beyond limits

I encountered strange behavior from Matlab when using the eps export. When I set up a figure like this:
subplot(2,1,1)
x = [duration([-3, 0, 0]), duration([-2, 0, 0]), duration([-1, 0, 0]), duration([0, 59, 59]), duration([1, 0, 0]), duration([2, 0, 0]), duration([3, 0, 0]), duration([3, 0, 1]), duration([5, 0, 0])];
y = [0, 0, 0, 0, 1, 1, 1, 0, 0];
plot(x,y)
set(gca,'XLim',[0 operationEnd-operationStart]);
xtickformat('hh:mm');
box off
subplot(2,1,2)
yyaxis left
plot(x,y)
yyaxis right
plot(x,y,'--');
set(gca,'XLim',[0 operationEnd-operationStart]);
xtickformat('hh:mm');
saveas(f,[PATH_SAVE,'eps_export_issue'],'eps2c');
The resulting figure looks in Matlab like this:
However when I open the exported EPS in Inkscape it seems to ignore the set XLim if the figure and it looks like this:
The issue also occurs if I don't use subplot and don't use duration as this snippet:
x = [-3, -2, -1, 0.99, 1, 2, 3, 3.01, 5];
y = [0, 0, 0, 0, 1, 1, 1, 0, 0];
f = figure();
yyaxis left
plot(x,y)
yyaxis right
plot(x,y,'--');
set(gca,'XLim',[0 4]);
box off
saveas(f,'eps_export_float','eps2c');
leads to an exported EPS that looks like this with the same issue:
How can I resolve this?

Data Plot in Matlab

I have two arrays say X and Y with same dimension. I can plot each points (x,y) by plot(X,Y). But how can I color them according to their given labels?
Say X = [3, 4, 2, 5, 6], Y = [2, 2, 1, 5, 6] and label = [1, 2, 2, [1,2], 2]. Here I all have to do is to color points with label=1 with blue and points in label=2 by red. How can I do this?
There are several ways to optimize this code and even get away without using the loop but this should get you started
for i=1:length(X)
xdot=X(i)
ydot=Y(i)
Ldot=label(i)
col=[1 0 0;0 0 1];
plot(xdot,ydot,'color',col(Ldot,:),'marker','o');
hold on
end

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

How to display two overlapping lines in 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);