File Exchange

## fit_logistic(t,Q)

version 1.9 (4.58 KB) by

Fit a time series to a best-fitting logistic function.

Updated

Fit time series Q(t) to a logistic function.
Inputs (vectors of same size): t (time) & Q
Outputs: Qpre (logistic model fit to data) and three independent parameters: thalf, Qinf, and a, describing the logistic
Q(t) = Qinf/(1 + exp(-a*(t-thalf)))
Qinf is value as t --> infinity
thalf is time of symmetric inflection point
a is time decay constant
Written by James Conder, Southern Illinois University, Oct. 2010
Cleaned up for publishing May 16, 2013

bozobec

### bozobec (view profile)

Please ignore my previous comment, it was a mistake from my side. Thanks a lot for this great script!

bozobec

### bozobec (view profile)

Hi everyone,

I am getting the following message: "Warning: Matrix is close to singular or badly scaled. Results may be inaccurate.
RCOND = 2.852389e-20. "

This happens with Q of range: 30e6 - 150e6. The code isn't optimised for these kind of values and I guess there is an issue then calculating the matrices that gives us the confidence limits.

Problem is fixed by dividing by 1e6 before, and multiply back by 1e6 once the fit is done.

Ildar Gilmutdinov

Joshua McAteer

### Joshua McAteer (view profile)

Really helpful. The output is in a different format to functions like polyfit, which confused me at first, but it seems to be robust and fast.

Thanks.

James Conder

### James Conder (view profile)

Waqas, that is a great suggestion. I just uploaded an update that will calculate the confidence limits. The 3rd output argument will be a 3 element vector with the 1-sigma confidence limits:
[Qpre, p, sm] = fit_logistic(t,Q)
So, parameter i = p(i) +/- sm(i).

Waqas Ullah

### Waqas Ullah (view profile)

Really great submission. Is there any way to get the confidence intervals for the parameters? At present I'm having to put the logistic formula into the curve fitting tool as a custom equation and put the parameters generated by fit_logistic in manually to get these.

James Conder

### James Conder (view profile)

Arman, you must be using an older version of MatLab. isrow is an intrinsic function available to 2011a(?) and later.

There is a MATLAB Central isrow submission from 2002 that will work for your version: http://www.mathworks.com/matlabcentral/fileexchange/1309-general-extra-toolbox/content/isrow.m

Best

arman goudarzi

### arman goudarzi (view profile)

Dear James

I have tried to run the codes with different values of "t" and "Q". But it keep giving me the below error:

??? Undefined function or method 'isrow' for input arguments of type 'double'.

Error in ==> fit_logistic at 62
if isrow(Q)

Sindy

### Sindy (view profile)

sorry...I tried to use the "message" provided by mathwork to contact you. Is this the right way to email you?

James Conder

### James Conder (view profile)

Sindy, the code doesn't do that as written, but could be modified at a handful of places to do it. Email me if you would like some help doing that.

Sindy

### Sindy (view profile)

Thanks for the sharing!
There are 3 parameters which is returned from fitting. If one of the parameter is fixed, for example, Qinf=1, can this function still be used?
Many thanks!

Ingrid

James Conder

### James Conder (view profile)

Note: Ingrid and I found the the reason for her straight line output. The function assumes that the tail begins at zero, while the initial tail of her data was at 7. It works as intended if the DC shift is removed from the data.

Ingrid

### Ingrid (view profile)

Does not work on my data (just gives me a straight line). Finally used the built in function nlinfit and this did work fine

James Conder

### James Conder (view profile)

Andrew, I spent some time looking at it, and think I have fixed the problem. I just uploaded a newer version. Once it is up, please try your dataset on it and let me know how it goes.

Andrew

### Andrew (view profile)

James,

Great function, thank you. I too have the issue with outputting a constant value for Qpre, and, as with Darren, changing the scaling of the value for t fixes this. My t values scale between 0 and 1 in steps of 0.001.

Many thanks

James Conder

### James Conder (view profile)

Hi Darren,

Sorry about the plotting calls. I realized that I forgot to remove them just after resubmitting. I guess the follow up submission with those removed is still moving though the system.

Good catch on reversing t. It is one of those bugs introduced when addressing a different problem. I'll fix that bug and put a test example in the help comments in new submission later today.

Darren Rowland

### Darren Rowland (view profile)

Hey James,

I've tested out the new code and it works a lot better for my case. One problem I've now identified is that you are not re-reversing t at the end of the function, so the calculated Qpre can be in error.

Other than this, I would suggest for you to include a brief usage example within the Help comments, e.g. constructing data from known parameters, adding some random error and obtaining parameter estimates. Just a few lines to help someone getting started.

Also, you should turn the various plotting calls off by default then have an extra (optional) input parameter for people to use to turn them on.

Hope that helps,
Darren

James Conder

### James Conder (view profile)

Thanks for the feedback, Darren. I've made a fix based on your idea of rescaling the vector internally, and submitted an update. It isn't completely obvious to me why Qpre goes to the mean of Q for some scalings of t. In any case, I hope my fix is general and not limited to your special case. Keep me posted.

Darren Rowland

### Darren Rowland (view profile)

Hi James,

This is a nice function but there is a failure condition to be aware of.

When I run the function on the following data, Qpre = 169.35 for all t. However, if I multiply t by 100, the function returns a better result.

Perhaps you can detect these cases and scale the vector internally to correct.

Darren

t = [0.8753
0.9267
0.9499
0.9678
0.9875
1.0206];
Q = [ 48.3871
96.7742
145.1613
193.5484
241.9355
290.3226];