Power function fitting graph: problem with tiledlayout
3 views (last 30 days)
Show older comments
Hello,
I have used the curve fitting tool to fit 3 different sets of data. So I proceeded to make a graph for each of the three sets of data as follows:
C1=[5e-3 2e-4 5e-5 1.25e-5]';
C2=[5e-3 2e-4 5e-5 1.25e-5 3e-6]';
l3070=[1703.125 37875 68893.75 69006.25]';
l7030=[22915.625 49525 42953.125 101265.625 156909.375]';
l8515=[26353.125 36665.625 79937.5 94287.5 89846.875]';
%%
[fit7030,data7030] = fit(C2,l7030,"power2");
figure(2)=plot(fit7030,'k-');
set(figure(2),'lineWidth',3);
hold on
plot(C2,l7030,'r*',MarkerSize=10);
legend('Location', 'northeast','FontSize',16,'NumColumns',1);
legend("Experimental Data","Power Fitting");
ylim([0 160000]);
xlim([0 0.005]);
%export as 600 dpi
filename = 'cf7030.png';
resolution = 600;
set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 10 8]);
print(gcf, filename, '-dpng', ['-r', num2str(resolution)]);
hold off
%%
[fit8515,data8515]=fit(C2,l8515,"power2");
figure(3)=plot(fit8515,'k-');
set(figure(3),'lineWidth',3)
hold on
plot(C2,l8515,'r*',MarkerSize=10);
legend('Location', 'northeast','FontSize',16,'NumColumns',1);
legend("Experimental Data","Power Fitting");
ylim([0 160000]);
xlim([0 0.005]);
%export as 600 dpi
filename = 'cf8515.png';
resolution = 600;
set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 10 8]);
print(gcf, filename, '-dpng', ['-r', num2str(resolution)]);
hold off
%%
[fit3070,data3070]=fit(C1,l3070,"power2");
figure(4)=plot(fit3070,'k-');
set(figure(4),'lineWidth',3);
hold on
plot(C1,l3070,'r*',MarkerSize=10);
legend('Location', 'northeast','FontSize',16,'NumColumns',1);
legend("Experimental Data","Power Fitting");
ax = gca;
ax.FontSize = 20;
ylim([0 160000]);
xlim([0 0.005]);
%export as 600 dpi
filename = 'cf3070.png';
resolution = 600;
set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 10 8]);
print(gcf, filename, '-dpng', ['-r', num2str(resolution)]);
hold off
As you can see, I get a fitted curve that approximates good enough for my needs. It's clear that I get an error for each of the graph, saying that non positive values are treated as NaNs. Although, I cannot seem to find any non positive values in my input data.
The problem arises when I try to make a tiled layout, and display these three graphs in a row. I have tried this:
x=10;
C1=[5e-3 2e-4 5e-5 1.25e-5]';
C2=[5e-3 2e-4 5e-5 1.25e-5 3e-6]';
l3070=[1703.125 37875 68893.75 69006.25]';
l7030=[22915.625 49525 42953.125 101265.625 156909.375]';
l8515=[26353.125 36665.625 79937.5 94287.5 89846.875]';
%%
t=tiledlayout(1,3);
[fit7030,data7030] = fit(C2,l7030,"power2");
nexttile
figure(2)=plot(fit7030,'k-');
set(figure(2),'lineWidth',3);
hold on
plot(C2,l7030,'r*',MarkerSize=10);
legend('Location', 'northeast','FontSize',x-2,'NumColumns',1);
legend("Experimental Data","Line Fitting");
ax = gca;
ax.FontSize = x-2;
ylim([0 160000]);
xlim([0 0.005]);
%%
[fit8515,data8515]=fit(C2,l8515,"power2");
nexttile
figure(3)=plot(fit8515,'k-');
set(figure(3),'lineWidth',3)
hold on
plot(C2,l8515,'r*',MarkerSize=10);
legend('Location', 'northeast','FontSize',x-2,'NumColumns',1);
legend("Experimental Data","Line Fitting");
ax = gca;
ax.FontSize = x-2;
ylim([0 160000]);
xlim([0 0.005]);
hold off
%%
[fit3070,data3070]=fit(C1,l3070,"power2");
nexttile
figure(4)=plot(fit3070,'k-');
set(figure(4),'lineWidth',3);
hold on
plot(C1,l3070,'r*',MarkerSize=10);
legend('Location', 'northeast','FontSize',x-2,'NumColumns',1);
legend("Experimental Data","Line Fitting");
ax = gca;
ax.FontSize = x-2;
ylim([0 160000]);
xlim([0 0.005]);
hold off
%export as 600 dpi
filename = 'tiled.png';
resolution = 600;
set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 14 8]);
print(gcf, filename, '-dpng', ['-r', num2str(resolution)]);
As you can see, leaving the huge discrepancies in the legend size (my bad), the real problem is that the curves when using tiledlayout are cut between 0 and 1 on the x-axis. Any idea why this is happening?
Thank you in advance.
Stefano
0 Comments
Accepted Answer
Voss
on 4 Apr 2024
Edited: Voss
on 4 Apr 2024
format long g
C1=[5e-3 2e-4 5e-5 1.25e-5]';
C2=[5e-3 2e-4 5e-5 1.25e-5 3e-6]';
l3070=[1703.125 37875 68893.75 69006.25]';
l7030=[22915.625 49525 42953.125 101265.625 156909.375]';
l8515=[26353.125 36665.625 79937.5 94287.5 89846.875]';
"the real problem is that the curves when using tiledlayout are cut between 0 and 1 on the x-axis. Any idea why this is happening?"
"plot(cfit) plots the curve given in the cfit object cfit over the range of the current axes (gca). If no current axes exist, the function plots the curve over the range of the data used to create cfit."
That statement explains why the behavior when plotting not in a tiledlayout is different than when in a tiledlayout: When not in a tiledlayout, there is no current axes (at least, none is created in your code), so the range of C2 (3e-6 to 5e-3) is used; when in a tiledlayout there is a current axes (because nexttile creates it), so the range of that axes (0 to 1) is used.
You can inspect the XData of the plotted line in each case to see the difference:
First, the no-tiledlayout case:
figure()
[fit7030,data7030] = fit(C2,l7030,"power2");
fig(2)=plot(fit7030,'k-');
xlim([0 0.005]);
get(fig(2),'XData').'
Now the tiledlayout case:
figure()
t=tiledlayout(1,3);
[fit7030,data7030] = fit(C2,l7030,"power2");
nexttile
fig(2)=plot(fit7030,'k-');
xlim([0 0.005]);
get(fig(2),'XData').'
Note that the XData of the line in the tiledlayout has a zero element, which explains the warning about x is required to be positive. The warning also explains why the line is cut off below x=0.001: the y-coordinate of the point at x=0 is NaN, and NaNs don't render on plots.
get(fig(2),'YData').'
So what to do about it? One way around the problem is to set the xlim of the tiledlayout axes before plotting:
figure()
t=tiledlayout(1,3);
[fit7030,data7030] = fit(C2,l7030,"power2");
nexttile
xlim([min(C2) max(C2)]) % setting xlim to range of C2
fig(2)=plot(fit7030,'k-');
xlim([0 0.005])
Now it looks like the no-tiledlayout case, and you can confirm that it is the same by checking the XData of the plotted line:
get(fig(2),'XData').'
2 Comments
Voss
on 4 Apr 2024
You're welcome!
To be honest, I had to step through the code to see where the difference happens and only after that did I look into the documentation for cfit plot and found the explanation. It wasn't obvious to me at all at first.
More Answers (1)
Emma Farnan
on 4 Apr 2024
When you plot a curve fit, it generates a line with 1001 x-points. When you let it autogenerate these x values in the tiledlayout, it chose to make those points from 0 to 1 to match the default axes generated by nexttile. That meant the first point > 0 was 0.001.
You should be able to get around this by making your own linspace of points and evaluating the curve at those points.
C2=[5e-3 2e-4 5e-5 1.25e-5 3e-6]';
l7030=[22915.625 49525 42953.125 101265.625 156909.375]';
[fit7030,data7030] = fit(C2,l7030,"power2");
xfit = linspace(0,0.005,2001); % Generate the x-points to evaluate the fit at
xfit = xfit(2:end); % Cut off the 0 to avoid the warning about power functions and negative values
yfit = fit7030(xfit); % Get the corresponding y values.
% Repeat for other fits
% Use this as the curve fit plot in your tiled layout plots
tiledlayout(1,3);
nexttile;
plot(xfit,yfit,'k-',C2,l7030,'r*',MarkerSize=10)
% Adjust axis as needed and then repeat for other tiles
0 Comments
See Also
Categories
Find more on Fit Postprocessing 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!