How to plot only a fitting curve in MATLAB? - matlab

I want to graph a fitting curve given vectors with X and Y values, but also some example points, as the vectors are really big (10k+ terms).
Here is an equivalent MWE of the problem I'm facing:
xData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
yData = [1.5, 2.6, 3.7, 4.8, 5.9, 7.0, 8.1, 9.2, 10.3, 11.4];
[pX, pY] = prepareCurveData(xData, yData);
ft = 'linearinterp';
[fitresult, gof] = fit( pX, pY, ft, 'Normalize', 'on' );
gX = xData(1:2:end);
gY = yData(1:2:end);
hold on;
plot(fitresult, pX, pY);
plot(gX, gY, 'k*');
And here is the result of the MWE. As you can see, I can plot the selected points (in black), but the plot(fitresult, pX, pY); command also plots all the points I used to the curve fitting process (the small, blue ones):
I tried with the plot(fitresult); command but with that I lose the fitted curve, although the data points are also not plotted.
So, is there a way to plot a fitted curve without its data points?

I edited the code according to the discussion in the comment:
xData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
yData = [1.5, 2.6, 3.7, 4.8, 5.9, 7.0, 8.1, 9.2, 10.3, 11.4];
[pX, pY] = prepareCurveData(xData, yData);
ft = 'linearinterp';
[fitresult, gof] = fit( pX, pY, ft, 'Normalize', 'on' );
% set the scale for a new plot
gX = 1:20;
gY = fitresult(gX);
plot(gX, gY, 'r'); axis tight;

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

plotting a curve in MATLAB with prefefined x-axis

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!

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

insert string within marker of matlab plot

I have a 2D line plot:
d3 = [1, 3, 5, 6, 8, 9];
plot(d3, '-ob');
I would like to know how to insert a value into the markers of the line plot, such as inserting the y values into the center of the markers. For example:
Would this be possible?
Use text and properly adjust the text properties to suit your purpose. You may have to play with the marker size and text alignment, but it's a fairly straightforward process.
For example:
% plot the data
figure
d3 = [1, 3, 5, 6, 8, 9];
n = 1:numel(d3);
plot(n,d3, '-ob','markersize',10,'markerfacecolor','w');
% step through the points in d3 and display a text label for each of them
for idx = 1:numel(d3)
text(n(idx),d3(idx), num2str(d3(idx)),...
'FontSize',8,...
'HorizontalAlignment','center');
end
There is a way of plotting digits in circle using some special fonts (for example, WingDings 2 has numbers in circle from digit 0 to 9). You may find some other free font with 2 digits in circle or square.
Here is the sample code.
font_numberCircle = 'WingDings 2';
x = 1:6;
y = rand(1,6);
m = {'j','l','n','o','q','r'}; %the markers to be plotted ('j' is 1 and 'r' is 9
figure('Color', 'w');
plot(x, y, 'r');
text(x, y, m, 'FontName', font_numberCircle, ...
'FontSize', 40, 'FontWeight', 'bold', ...
'HorizontalAlignment', 'center' )
set(gca, 'XLim', [0 7], 'YLim', [-0.1 1.1] );

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