Search code examples
matlabgraphsigmoid

How to create a dose response curve in MATLAB? doseResponse function rank deficient warning


I've been searching for a way to create dose response curves from data within MATLAB. So far, I've been running the doseResponse function downloaded from here. However, I've been having trouble generating a sigmoidal curve that fits my data. By running the following code, I get the following error and produce the following graph. I also uploaded my data to google drive here. Does anyone know how I can fix this? Or does anyone know of a better way to produce dose response curves? Thanks.

Code

doseResponse(drug_conc,resp_vals)
xlabel('5HT Dose (nm)','FontSize',20) 
ylabel('Normalized Response to Stimuli (\DeltaF / F)','FontSize',20)'

Warning Message

Warning: Rank deficient, rank = 3, tol =  1.196971e-11. 
> In nlinfit>LMfit (line 587)
In nlinfit (line 284)
In doseResponse (line 47)
Warning: Rank deficient, rank = 1, tol =  3.802134e-12. 
> In nlinfit>LMfit (line 587)
In nlinfit (line 284)
In doseResponse (line 47)
Warning: Some columns of the Jacobian are effectively zero at the solution, indicating that the model is insensitive to some of its parameters.
That may be because those parameters are not present in the model, or otherwise do not affect the predicted values.  It may also be due to
numerical underflow in the model function, which can sometimes be avoided by choosing better initial parameter values, or by rescaling or
recentering.  Parameter estimates may be unreliable. 
> In nlinfit (line 381)
In doseResponse (line 47) 
ans =
-5.2168e+07

enter image description here


Solution

  • Major of rank deficit problem during non-linear curve fitting comes from wrong initial value setting. You may refer to John's answer for the recognition of its importance. In case of the doseRespose function you used. The code was formulated as below for sigmoid curve fitting.

    %calculate some rough guesses for initial parameters
    minResponse=min(response);
    maxResponse=max(response);
    midResponse=mean([minResponse maxResponse]);
    minDose=min(dose);
    maxDose=max(dose);
    %fit the curve and compute the values
    [coeffs,r,J]=nlinfit(dose,response,sigmoid, [minResponse maxResponse midResponse 1]);
    

    The initial cofficients for sigmoid was estimated using min, and max values of given dose and response. I'm not sure if that's the convention in the field of drug-response plot. However if not, you may use a smarter way to estimate the initial values of those if you have access to Optimization Toolbox.

    lsqcurvefit(sigmoid, [minResponse maxResponse midResponse 1], dose, response);
    > [0.898627445275206,-0.0795383479232744,57.8616285607284,0.537847599487817]
    

    It can do two things that the Statistics Toolbox functions cannot: (1) accept bounds on the parameters, and (2) fit matrix dependent variables (https://kr.mathworks.com/matlabcentral/answers/131109-parameter-estimation-nlinfit-vs-fitnlm), and therefore provide better estimation. Afterward, simple substitution will give you the desired result.

    %fit the curve and compute the values
    beta_new = [0.898627445275206,-0.0795383479232744,57.8616285607284,0.537847599487817];
    [coeffs,r,J]=nlinfit(dose,response,sigmoid, beta_new);
    

    Modified