Fitting system of ODEs to data using lsqcurvefit and ode45
Show older comments
I am fitting a system of 3 differential equations that model change in concentrations of molecules over time to experimental data. I'd like to optimize four parameters in the third equation (theta(1), theta(2), theta(3), theta(4)). I am receiving an error message that the initial point is a local minimum. I've tried changing the initial theta values with no luck, as well as changing optimality and function tolerance. Additionally, the last 3 rows of output vector C are NaN and I'm not sure why (this is why I included the line C(find(isnan(C))) = 0;). Any help would be greatly appreciated!
function C = kinetics(theta,t)
c0 = [0 0 0]; %[AA_conc BB_conc MKATE2]
[T,Cv]=ode45(@DifEq,t,c0);
function dC = DifEq(t,c)
dcdt=zeros(3,1);
AA_conc = c0(1);
BB_conc = c0(2);
MKATE2 = c0(3);
nH_Est = 1.2; % Hill for Est known
nH_Ald = 1.2; % Hill for Ald known
nH_het = 1.2; %
kact = 1; % Transcriptional activation rate for all equations
kdeg1 = 0.01; % Degredation rate of AA
kdeg2 = 0.01;
ec501 = 64; %nM, known (Est)
ec502 = 200; %nM, known (Ald)
tmin = 0; % start time
tmax = 900; % end time (min.)
inc = 17; % # of time steps
time = linspace(tmin,tmax,inc);
ON_time = 900; % Units = min.
OFF_time = 0; % Units = min.
Est = 100*[ones(1,(ON_time/tmax)*inc) zeros(1,(OFF_time/tmax)*inc)];
ON_A = 900; %ON for aldosterone, units = min
OFF_A = 0; %OFF for aldosterone, units = min
Ald = 100*[ones(1,(ON_A/tmax)*inc) zeros(1,(OFF_A/tmax)*inc)]; %units = nM
EstI = interp1(time,Est,t)';
AldI = interp1(time,Ald,t)';
dcdt(1) = kact.*[EstI].^nH_Est./([EstI].^nH_Est + ec501.^nH_Est) - kdeg1.*c(1);
dcdt(2) = kact.*[AldI].^nH_Ald./([AldI].^nH_Ald + ec502.^nH_Ald) - kdeg2.*c(2);
dcdt(3) = kact.*[c(1).*c(2)./(theta(3)).^0.5]^theta(4)./([c(1).*c(2)./(theta(3)).^0.5].^theta(4) + theta(2).^nH_het) - theta(1).*c(3);
dC=dcdt;
end
C=Cv(:,3);
C(find(isnan(C))) = 0;
end
To read in the experimental data and call the function:
%% read in experimental data
simVal = readtable('08Dec21_Table.xlsx');
sim330 = simVal.yAS330;
sim330 = sim330';
simTime = [15,18:32,45];
simTime = simTime.*60;
%% fitting
sim330 = 100*sim330./max(sim330);
t=simTime';
c=sim330';
theta0=[kdeg3;ec503;kobs;nH_het];
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c);
The function currently returns the initial theta parameters without optimizing. Below is a plot of the solution to the third differential equation (using initial theta values) overlaid with the experimental data. I can provide additional information as needed. Thanks!!
5 Comments
Star Strider
on 28 Apr 2022
Don’t do this:
c0 = [0 0 0]; %[AA_conc BB_conc MKATE2]
Estimate the initial conditions with the other parameters, appending them as the last elements in the parameter vector. Change the code in ‘Kinetics’ accordingly to accommodate that.
Hannah Collins
on 28 Apr 2022
Star Strider
on 28 Apr 2022
In ‘Kinetics’ the ‘c0’ vector needs to be:
c0 = theta(5:7);
Append three non-zero values (they can be near zero) to the existing ‘theta0’ vector and go from there.
You coded this correctly the first time:
[T,Cv]=ode45(@DifEq,t,c0);
then changed it in the Comment.
Hannah Collins
on 28 Apr 2022
Star Strider
on 28 Apr 2022
Without the data, I can¹t determine what the problem is. Sometimes it’s just necessary to keep experimenting with different initial parameter estimates to see what works best, the reason I generally use random numbers for the initial parameter estimates (scaled appropriately). If you have the Global Optimization Toolbox, I’ll post a ga (genetic algorithm) approach to this problem that generally works. Otherwise, keep trying different initial parameter estimates until one provides a good fit. That’s simply the way nonlilnear parameter estimation works.
Answers (0)
Categories
Find more on Get Started with Curve Fitting Toolbox 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!