# Plotting a faired curve through a data set that curves in on itself

8 views (last 30 days)
Jayden on 13 Apr 2024
Commented: Mathieu NOE on 28 May 2024 at 17:44
I am trying to plot a curve that goes through all the points in my data set using a fit method. I have tried using interp1 with smoothing spline and makima, I have tried fit, and I have tried polyfit. In all cases it does not work. My data set is values of CM (pitching moment) vs CL (lift coefficient). The first 11 of my 14 data points are increasing CL and decreasing CM, but then from the 12th to 14th data points, my values of CL decrease whilst the values of CM also decrease (due to stall). In this way, the curve goes in on itself. My question is, is there a way to plot a single curve that goes through (or at least mostly) goes through all of the points even though CL is not strictly increasing over the entire interval?
Here is what the raw data looks like:
Any help would be greatly appreciated. Many thanks in advance.
John D'Errico on 13 Apr 2024
Edited: John D'Errico on 13 Apr 2024
As you have been told, you CANNOT model this as a function. You CANNOT use interp1 as you are trying to do, or to use fit directly. In all those cases, trying to model C_M as a function of C_L would result in something that is not a single valued function. That is, for C_L == 1.3, exactly which single choice for C_M should the model return? That is what a single valued function would do. And that is why your attempts with a spline, with a polynomial, with interp1, etc. all failed. Any such tool MUST presume a single valued function. For any give value of x, there would be EXACTLY one y.
What can you do? You can use tools like cscvn. It allows a non-single valued function. Curves by that tool can follow any set of points you give it. The result will NOT be a simple function you can evaluate however, because again, if you want to evaluate a function, it must be single valued!
The other choice is to swap x and y, as has been suggested. In this case, swapping the relationship results in a single valued function that can be fit. (That need not always be the case. for example with points around a circle.) Once you do that on your data however, the result is a single valued relationship, x(y). Here that would be C_L(C_M). But it cannot predict in the other direction. How could it do that? If all you want to do is plot a curve from that data, you could do this:
CL = [-0.117323468280501
0.109533077818298
0.349535877911274
0.578159011570390
0.799525368741050
0.989291914638142
1.15205588979230
1.23246920496028
1.29909262861280
1.35437407382001
1.35912940969856
1.34136836172825
1.29541307340786
1.11501423385178];
CM = [0.150258158337099
0.117407098855973
0.0884047743485015
0.0670114607977137
0.0517955492445810
0.0305383477518936
0.00355285590629767
-0.00978950167650419
-0.0257317663408145
-0.0378647559486718
-0.0873543217991825
-0.0904845481307666
-0.103361954196992
-0.184021637962439];
spl = cscvn([CL,CM]')
spl = struct with fields:
form: 'pp' breaks: [0 0.4788 0.9705 1.4496 1.9207 2.3577 2.7639 3.0494 3.3111 3.5490 3.7720 3.9063 4.1247 4.5693] coefs: [26x4 double] pieces: 13 order: 4 dim: 2
fnplt(spl)
hold on
plot(CL,CM,'ro')
xlabel 'C_L'
ylabel 'C_M'
hold off
It is a little bumpy on the right, but that is due to it trying to interpolate those points exactly. It needed to make some sharp turns. The curve generated by @Voss using a smoothing spline is nicer (smoother) looking, but it does not interpolate the data. You could also do this, as a pure interpolant:
spl2 = spline(CM,CL);
plot(CL,CM,'ro')
CMint = linspace(min(CM),max(CM));
hold on
plot(fnval(spl2,CMint),CMint,'-b')
xlabel 'C_L'
ylabel 'C_M'
hold off
So you need to make a choice. If all you want to do here is plot a smooth curve through the data, then there are at least a few options, depending on how smooth of a curve you want. Do you want a curve that follows the data exactly? Thus, an interpolant? Do you want a smoother curve, that comes close to the data?
Jayden on 13 Apr 2024
Thank you very much John for your insight. I see that trying to fit a curve to non-monotonic data sets is not as straightforward as I initially hoped! Can I ask what the benefit of using interpolation as opposed to smoothing spline is? As I understand it you can obtain R squared values and rmse from fit so is it just that interpolation can be applied to data set outside of original range of points? Sorry if my understanding of this is flawed.
Another approach I considered was trying to express CL and CM both as a function of some other parameter, say t, to allow me to plot(x,y,t) but I was unsure of how to find the t parameter given a set of data X, Y. Would this also be a valid approach?

Mathieu NOE on 16 Apr 2024
Edited: Mathieu NOE on 16 Apr 2024
hello
experimental airfoil data can exibit some randomness especially at high angle of attack (stall)
we usually prefer to smooth the data rather to go exactly through the points (IMHO)
so a very simple code that interpolates and smooth the data :
CL = [-0.117323468280501
0.109533077818298
0.349535877911274
0.578159011570390
0.799525368741050
0.989291914638142
1.15205588979230
1.23246920496028
1.29909262861280
1.35437407382001
1.35912940969856
1.34136836172825
1.29541307340786
1.11501423385178];
CM = [0.150258158337099
0.117407098855973
0.0884047743485015
0.0670114607977137
0.0517955492445810
0.0305383477518936
0.00355285590629767
-0.00978950167650419
-0.0257317663408145
-0.0378647559486718
-0.0873543217991825
-0.0904845481307666
-0.103361954196992
-0.184021637962439];
% interpolate
CM2 = linspace(min(CM),max(CM),100);
CL2 = interp1(CM,CL,CM2,'linear');
% smooth
N = 20;
CL2s = smoothdata(CL2,'lowess',N);
plot(CL,CM,'*-');
hold on
plot(CL2s,CM2,'-');
xlabel 'C_L'
ylabel 'C_M'
hold off
Mathieu NOE on 28 May 2024 at 17:44
hello again
problem solved ?