Constraining parameters in nonlinear fit

16 views (last 30 days)
Tim
Tim on 20 Feb 2014
Commented: Shashank Prasanna on 24 Feb 2014
Hi,
I am trying to constrain the parameters of my fit, but I am unable to do so. I am reading data from an oscilloscope and trying to fit a sine wave to it. I'd like to force the amplitude to be positive and the phase angle to be between 0 and 2*pi. The relevant section of my code is below. The way I'm setting the options must be incorrect. Any advice would be much appreciated. Thank you in advance.
Tim
%%Fitting
freq = 25000000; % temporary. Use user input in reality: 10^6*input(prompt);
x = waveform.XData';
v = waveform.YData;
g = fittype(@(a,b,c,x) a*sin(2*pi*freq*x+b)+c);
options = fitoptions(g);
options.Method = NonlinearLeastSquares;
options.Robust = Off;
options.Algorithm = trust-region-reflective;
options.Unknowns = [a,b,c];
options.Lower = [0,0,-Inf];
options.Upper = [+Inf,2*pi,+Inf];
[f,gof,output] = fit(x,v,g,options)
plot(f,x,v)

Answers (2)

John D'Errico
John D'Errico on 20 Feb 2014
The amplitude as a positive number is a meaningless requirement, since a sine wave is both positive and negative. Shift the phase, and the amplitude (as you seem to want to define it) changes sign. All that matter is the absolute value of that coefficient.
As far as something being incorrect, why not tell us why you think it to be incorrect? Are you getting an error? If so, paste in the text of the error.
  1 Comment
Tim
Tim on 20 Feb 2014
Hi John, thanks for your answer. A little more info on my problem...
I am recording the waveform from an oscilloscope channel at certain intervals (say, every 10 seconds). I then want to examine how the amplitude changes over time to see if there are any variations in the signal when certain physical affects are applied to the signal source. I also want to examine the phase over time for the same reason.
A negative amplitude versus a positive one corresponds to an additional phase angle of pi, which I don't want. The reason for wanting to constrain it is that the fitting algorithm will arbitrarily make the amplitude positive or negative, affecting the phase angle, which would show up in my plot of phase over time but not correspond to the phenomena I wish to observe. The amplitude would also flip arbitrarily between positive and negative values over time, though I agree I can just look at it's absolute value. Similarly to above, the fitting algortithm will assign a positive or negative value to the phase that can be outside the range of 0 to 2*pi, which again is problematic if I choose to examine phase over time.
The other option is to examine the coefficients and make the amplitude positive if it is negative, and subtract a factor of pi from the phase. Then, I can just add or subtract factors of 2*pi from the coefficients as required until they are within the range I want. However, this is a more laborious way of doing it and if the option to avoid this is there, I'd take it.
In answer to your other question, I get the error:
Undefined function or variable 'NonlinearLeastSquares'.
Thanks again, Tim

Sign in to comment.


Shashank Prasanna
Shashank Prasanna on 20 Feb 2014
Regarding the Error: Provide the method with quotations
options.Method = 'NonlinearLeastSquares';
Here is an example that uses NonlinearLeastSquares:
  2 Comments
Tim
Tim on 21 Feb 2014
Edited: Tim on 21 Feb 2014
Hi Shashank,
Thanks for your response. I tried placing the different string arguments in inverted commas, but had no luck. If I write:
options.Method = 'NonlinearLeastSquares';
I receive the error:
Changing the 'Method' property of curvefit.basefitoptions is not allowed.
If I comment out this line, MATLAB errors next at:
options.Algorithm = 'trust-region-reflective';
with the response:
There is no enumerated value named 'trust-region-reflective'.
Again, if I comment out this line MATLAB errors at:
options.Unknowns = ['a','b','c'];
with the response:
Unidentified function or variable 'a'.
Finally, if I also comment out this line I do get a fit, but it is very bad and appears as a straight line rather than a sine wave.
The next thing I tried was replacing the fitting section with this:
freq = 25000000; % temporary. Use user input in reality: 10^6*input(prompt);
x = waveform.XData';
v = waveform.YData;
s = fitoptions('Method','NonlinearLeastSquares',...
'Lower',[0,0,-Inf],...
'Upper',[Inf,2*pi,Inf],...
'Startpoint',[0,0,-15]);
h = fittype(@(a,b,c,x) a*sin(2*pi*freq*x+b)+c, 'options',s);
[f,gof,output] = fit(x,v,h)
based on the census example you linked to. This gives an equally bad fit, with the same results (see picture). The data points also seem to lie outside the range of the y-axis.
I may have to settle for just manually bringing the fitted values into range after the fitting algorithm has done it's work. This is annoying, but I can't see another solution.
Thanks again.
Shashank Prasanna
Shashank Prasanna on 24 Feb 2014
Hi Tim, The last option you tried with fitoptions to provide the options is the recommended approach. For other recommended approaches to specify fit options see the following link:
I'll try and recommend something that may help. Use the cftool app and choose a predefined library function called sum-of-sines as shown here:
Here you can visually verify if you are able to get a fit. If not enforce constraints using the fit options button. If this leads you to a good fit, use the File menu to automatically generate MATLAB code for you.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!