simulate the glucose-凯发k8网页登录
this example shows how to simulate and analyze a model in simbiology® using a physiologically based model of the glucose-insulin system in normal and diabetic humans.
this example requires statistics and machine learning toolbox™ and optimization toolbox™.
references
meal simulation model of the glucose-insulin system. c. dalla man, r.a. rizza, and c. cobelli. ieee transactions on biomedical engineering (2007) 54(10), 1740-1749.
a system model of oral glucose absorption: validation on gold standard data. c. dalla man, m. camilleri, and c. cobelli. ieee transactions on biomedical engineering (2006) 53(12), 2472-2478.
aims
implement a simbiology model of the glucose-insulin response.
simulate the glucose-insulin response to one or more meals for normal and impaired (diabetic) subjects.
perform parameter estimation using
sbiofit
with a forcing function strategy.
background
in their 2007 publication, dalla man et al. developed a model for the human glucose-insulin response after a meal. this model describes the dynamics of the system using ordinary differential equations. the authors used their model to simulate the glucose-insulin response after one or more meals, for normal human subjects and human subjects with various kinds of insulin impairments. the impairments were represented as alternate sets of parameter values and initial conditions.
we implemented the simbiology model, m1
, by:
translating the model equations in dalla man et al. (2007) into reactions, rules, and events.
organizing the model into two compartments, one for glucose-related species and reactions (named
glucose appearance
) and one for insulin-related species and reactions (namedinsulin secretion
).using the parameter values and initial conditions from the model equations and from table 1 and figure 1.
including an equation for the gastric emptying rate as presented in dalla man et al. (2006).
setting the units for all species, compartments, and parameters as specified by dalla man et al. (2007), which allows the simbiology model to be simulated using unit conversion. (note that simbiology also supports the use of dimensionless parameters by setting their
valueunits
property todimensionless
.)setting the configuration set
timeunits
tohour
, since simulations were conducted over 7 or 24 hours.using a basis of 1 kilogram of body weight to transform species and parameters that were normalized by body weight in the original model. doing so made species units in amount or concentration, as required by simbiology.
we represented the insulin impairments in the simbiology model as variant objects with the following names:
type 2 diabetic
low insulin sensitivity
high beta cell responsivity
low beta cell responsivity
high insulin sensitivity
we represented the meals in the simbiology model as dose objects:
a dose named
single meal
represents a single meal of 78 grams of glucose at the start of a simulation.a dose named
daily life
represents one day's worth of meals, relative to a simulation starting at midnight: breakfast is 45 grams of glucose at 8 hours of simulation time (8 a.m.), lunch is 70 grams of glucose at 12 hours (noon), and dinner is 70 grams of glucose at 20 hours (8 p.m.).
a diagram of the simbiology model is shown below:
setup
load the model.
sbioloadproject('insulindemo', 'm1')
suppress an informational warning that is issued during simulations.
warnsettings = warning('off', 'simbiology:dimanalysisnotdone_matlabfcn_dimensionless');
simulating the glucose-insulin response for a normal subject
select the single meal
dose object and display its properties.
mealdose = sbioselect(m1, 'name', 'single meal'); get(mealdose)
ans = struct with fields:
amount: 78
interval: 0
rate: 0
repeatcount: 0
starttime: 0
active: 0
amountunits: 'gram'
durationparametername: ''
eventmode: 'stop'
lagparametername: ''
rateunits: ''
targetname: 'dose'
timeunits: 'hour'
name: 'single meal'
parent: [1x1 simbiology.model]
notes: ''
tag: ''
type: 'repeatdose'
userdata: []
simulate for 7 hours.
configset = getconfigset(m1,'active');
configset.stoptime = 7;
display the simulation time units (and stoptime
units).
configset.timeunits
ans = 'hour'
simulate a single meal for a normal subject.
normalmealsim = sbiosimulate(m1, configset, [], mealdose);
simulating the glucose-insulin response for a type 2 diabetic
select the type 2 diabetic variant and display its properties.
diabeticvar = sbioselect(m1, 'name', 'type 2 diabetic')
diabeticvar = simbiology variant - type 2 diabetic (inactive) contentindex: type: name: property: value: 1 parameter plasma volume ... value 1.49 2 parameter k1 value .042 3 parameter k2 value .071 4 parameter plasma volume ... value .04 5 parameter m1 value .379 6 parameter m2 value .673 7 parameter m4 value .269 8 parameter m5 value .0526 9 parameter m6 value .8118 10 parameter hepatic extrac... value .6 11 parameter kmax value .0465 12 parameter kmin value .0076 13 parameter kabs value .023 14 parameter kgri value .0465 15 parameter f value .9 16 parameter a value 6e-05 17 parameter b value .68 18 parameter c value .00023 19 parameter d value .09 20 parameter kp1 value 3.09 21 parameter kp2 value .0007 22 parameter kp3 value .005 23 parameter kp4 value .0786 24 parameter ki value .0066 25 parameter [ins ind glu u... value 1.0 26 parameter vm0 value 4.65 27 parameter vmx value .034 28 parameter km value 466.21 29 parameter p2u value .084 30 parameter k value .99 31 parameter alpha value .013 32 parameter beta value .05 33 parameter gamma value .5 34 parameter ke1 value .0007 35 parameter ke2 value 269.0 36 parameter basal plasma g... value 164.18 37 parameter basal plasma i... value 54.81
simulate a single meal for a type 2 diabetic.
diabeticmealsim = sbiosimulate(m1, configset, diabeticvar, mealdose);
compare the results for the most important outputs of the simulation.
plasma glucose (species
plasma glu conc
)plasma insulin (species
plasma ins conc
)endogenous glucose production (parameter
glu prod
)glucose rate of appearance (parameter
glu appear rate
)glucose utilization (parameter
glu util
)insulin secretion (parameter
ins secr
)
outputnames = {'plasma glu conc', 'plasma ins conc', 'glu prod', ... 'glu appear rate', 'glu util', 'ins secr'}; figure; for i = 1:numel(outputnames) subplot(2, 3, i); [tnormal, ynormal ] = normalmealsim.selectbyname(outputnames{i}); [tdiabetic, ydiabetic] = diabeticmealsim.selectbyname(outputnames{i}); plot( tnormal , ynormal , '-' , ... tdiabetic , ydiabetic , '--' ); % annotate figures outputparam = sbioselect(m1, 'name', outputnames{i}); title(outputnames{i}); xlabel('time (hour)'); if strcmp(outputparam.type, 'parameter') ylabel(outputparam.valueunits); else ylabel(outputparam.initialamountunits); end xlim([0 7]); % add legend if i == 3 legend({'normal', 'diabetic'}, 'location', 'best'); end end
note the much higher concentrations of glucose and insulin in the plasma, as well as the prolonged duration of glucose utilization and insulin secretion.
simulating one day with three meals for a normal subject
set the simulation stoptime
to 24 hours.
configset.stoptime = 24;
select daily meal dose.
daydose = sbioselect(m1, 'name', 'daily life');
simulate three meals for a normal subject.
normaldaysim = sbiosimulate(m1, configset, [], daydose);
simulating one day with three meals for impaired subjects
simulate the following combinations of impairments:
impairment 1: low insulin sensitivity
impairment 2: impairment 1 with high beta cell responsivity
impairment 3: low beta cell responsivity
impairment 4: impairment 3 with high insulin sensitivity
store the impairments in a cell array.
impairvars{1} = sbioselect(m1, 'name', 'low insulin sensitivity' ) ; impairvars{2} = [impairvars{1}, ... sbioselect(m1, 'name', 'high beta cell responsivity')]; impairvars{3} = sbioselect(m1, 'name', 'low beta cell responsivity' ) ; impairvars{4} = [impairvars{3}, ... sbioselect(m1, 'name', 'high insulin sensitivity' )];
simulate each impairment.
for i = 1:4 impairsims(i) = sbiosimulate(m1, configset, impairvars{i}, daydose); end
compare the plasma glucose and plasma insulin results.
figure; outputnames = {'plasma glu conc', 'plasma ins conc'}; legendlabels = {{'normal'}, ... {'-ins =\beta', '-ins \beta'}, ... {'=ins -\beta', ' ins -\beta'}}; ylimits = [80 240; 0 500]; for i = 1:numel(outputnames) [tnormal, ynormal] = selectbyname(normaldaysim , outputnames{i} ); [timpair, yimpair] = selectbyname(impairsims , outputnames{i} ); % plot normal subplot(2, 3, 3*i-2 ); plot(tnormal, ynormal, 'b-'); xlim([0 24]); ylim(ylimits(i,:)); xlabel('time (hour)'); legend(legendlabels{1}, 'location', 'northwest'); % plot low insulin subplot(2, 3, 3*i-1 ); plot(timpair{1}, yimpair{1}, 'g--', timpair{2}, yimpair{2}, 'r:'); xlim([0 24]); ylim(ylimits(i,:)); xlabel('time (hour)'); legend(legendlabels{2}, 'location', 'northwest'); title(outputnames{i}); % plot low beta subplot(2, 3, 3*i ); plot(timpair{3}, yimpair{3}, 'c-.', timpair{4}, yimpair{4}, 'm-'); xlim([0 24]); ylim(ylimits(i,:)); xlabel('time (hour)'); legend(legendlabels{3}, 'location', 'northwest'); end
note that either low insulin sensitivity (dashed green line, ) or low beta-cell sensitivity (dashed-dotted cyan line, ) lead to increased and prolonged plasma glucose concentrations (top row of plots). low sensitivity in one system can be partially compensated by high sensitivity in another system. for example, low insulin sensitivity and high beta-cell sensitivity (dotted red line, ) results in relatively normal plasma glucose concentrations (top row of plots). however, in this case, the resulting plasma insulin concentration is extremely high (bottom row of plots).
parameter estimation methodology
rather than simultaneously estimating parameters for the entire model, the authors perform parameter estimation for different subsystems of the model using a forcing function strategy. this approach requires additional experimental data for the "inputs" of the submodel. during fitting, the input data determine the dynamics of the inputs species. (in the full model, the dynamics of the inputs are determined from the differential equations.) in simbiology terms, you can implement a forcing function as a repeated assignment rule that controls the value of a species or parameter that serves as an input for a subsystem of the model. in the following sections, we use the parameter fitting capabilities of simbiology to refine the authors' reported parameter values.
fitting the gastrointestinal model of glucose appearance using nlinfit
the gastrointestinal model represents how glucose in a meal is transported through the stomach, gut, and intestine, and then absorbed into the plasma. the input to this subsystem is the amount of glucose in a meal, and the output is the rate of appearance of glucose in the plasma. however, we also estimate the meal size since the value reported by the authors is inconsistent with the parameters and simulation results. because this input only occurs at the start of the simulation, no forcing function is required.
the function sbiofit
supports the estimation of parameters in simbiology models using several different algorithms from matlab™, statistics and machine learning toolbox, optimization toolbox, and global optimization toolbox. first, estimate the parameters using statistics and machine learning toolbox function nlinfit
.
% load the experimental data fitdata = groupeddata(readtable('glucosedata.csv', 'delimiter', ',')); % set the units on the data fitdata.properties.variableunits = {... 'hour', ... % time units 'milligram/minute', ... % glurate units 'milligram/deciliter', ... % plasmagluconc units 'milligram/minute', ... % gluutil units }; % identify which model components corresponds to observed data variables. gastrofitobs = '[glu appear rate] = glurate'; % estimate the value of the following parameters: gastrofitest = estimatedinfo({'kmax', 'kmin', 'kabs', 'dose'}); % ensure the parameter estimates are always positive during estimation by % using a log transform on all parameters. [gastrofitest.transform] = deal('log'); % set the initial estimate for dose to the reported meal dose amount. the % remaining initial estimates will be taken from the parameter values in % the model. gastrofitest(4).initialvalue = mealdose.amount; % generate simulation data with the initial parameter estimates configset.stoptime = 7; gastroinitsim = sbiosimulate(m1, mealdose); % fit the data using |nlinfit|, displaying output at each iteration fitoptions = statset('display', 'iter'); [gastrofitresults, gastrofitsims] = sbiofit(m1, fitdata, ... gastrofitobs, gastrofitest, [], 'nlinfit', fitoptions);
norm of norm of iteration sse gradient step ----------------------------------------------------------- 0 43.798 1 2.23537 22.9971 0.596828 2 1.65217 1.33015 0.107431 3 1.6491 0.0778864 0.0239157 4 1.64909 0.000586249 0.00224475 5 1.64909 0.0141494 0.000316238 6 1.64909 0.0139995 2.23854e-05 7 1.64909 0.00971641 2.33353e-05 8 1.64909 0.00786815 2.28944e-05 9 1.64909 0.0098386 2.52605e-05 10 1.64909 0.00541449 2.43141e-07 iterations terminated: relative change in sse less than options.tolfun
fitting the data using fminunc
now, estimate the parameters using the optimization toolbox function fminunc
.
% fit the data, plotting the objective function at each iteration fitoptions2 = optimoptions('fminunc', 'plotfcns', @optimplotfval); [gastrofitresults(2), gastrofitsims(2)] = sbiofit(m1, fitdata, ... gastrofitobs, gastrofitest, [], 'fminunc', fitoptions2);
compare the simulation before and after fitting.
gastrosims = selectbyname([gastroinitsim gastrofitsims], 'glu appear rate'); figure; plot(gastrosims(1).time , gastrosims(1).data , '-' , ... gastrosims(2).time , gastrosims(2).data , '--' , ... gastrosims(3).time , gastrosims(3).data , '-.' , ... fitdata.time , fitdata.glurate, 'x' ); xlabel('time (hour)'); ylabel('mg/min'); legend('reported', 'estimated (nlinfit)', ... 'estimated (fminunc)', 'experimental'); title('glucose appearance fit');
plot the change in parameter values, relative to reported values.
figure; fitresults = [gastrofitresults(1).parameterestimates.estimate ... gastrofitresults(2).parameterestimates.estimate]; % the initial values for kmax, kmin, and kabs come from the model. gastrofitinitvalues = [ get(sbioselect(m1, 'name', 'kmax'), 'value') get(sbioselect(m1, 'name', 'kmin'), 'value') get(sbioselect(m1, 'name', 'kabs'), 'value') gastrofitest(4).initialvalue ]; relfitchange = fitresults ./ [gastrofitinitvalues gastrofitinitvalues] - 1; bar(relfitchange); ax = gca; ax.xticklabel = {gastrofitest.name}; ylabel('relative change in estimated values'); title('comparing reported and estimated gastrointestinal parameter values'); legend({'nlinfit', 'fminunc'}, 'location', 'north')
note that the model fits the experimental data significantly better if the meal size (dose
) is significantly larger than reported, the parameter kmax
is significantly larger than reported, and kabs
is smaller than reported.
fitting the muscle and adipose tissue model of glucose utilization
the muscle and adipose tissue model represents how glucose is utilized in the body. the "inputs" to this subsystem are the concentration of insulin in the plasma (plasma ins conc
), the endogenous glucose production (glu prod
), and the rate of appearance of glucose (glu appear rate
). the "outputs" are the concentration of glucose in the plasma (plasma glu conc
) and the rate of glucose utilization (glu util
).
because the inputs are a function of time, they need to be implemented as forcing functions. specifically, the values of plasma ins conc
, glu prod
, and glu appear rate
are controlled by repeated assignments that call functions to do linear interpolation of the reported experimental values. when using these functions to control a species or parameter, you must make inactive any other rule that is used to set its value. to facilitate the selection of these rules, the rule name properties contain meaningful names.
% create forcing functions for the "inputs": % plasma insulin plasmainsrule = sbioselect(m1, 'name', 'plasma ins conc definition'); plasmainsforcingfcn = sbioselect(m1, 'name', 'plasma ins conc forcing function')
plasmainsforcingfcn = simbiology rule array index: ruletype: rule: 1 repeatedassignment [plasma ins conc] = [picomole per liter]*plasmainsulin(time/[one hour])
plasmainsrule.active = false; plasmainsforcingfcn.active = true; % endogenous glucose production (glu prod) gluprodrule = sbioselect(m1, 'name', 'glu prod definition'); gluprodforcingfcn = sbioselect(m1, 'name', 'glu prod forcing function')
gluprodforcingfcn = simbiology rule array index: ruletype: rule: 1 repeatedassignment [glu prod] = [milligram per minute]*endogenousglucoseproduction(time/[one hour])
gluprodrule.active = false; gluprodforcingfcn.active = true; % glucose rate of appearance (glu appear rate) gluraterule = sbioselect(m1, 'name', 'glu appear rate definition'); glurateforcingfcn = sbioselect(m1, 'name', 'glu appear rate forcing function')
glurateforcingfcn = simbiology rule array index: ruletype: rule: 1 repeatedassignment [glu appear rate] = [milligram per minute]*glucoseappearancerate(time/[one hour])
gluraterule.active = false; glurateforcingfcn.active = true; % simulate with the initial parameter values muscleinitsim = sbiosimulate(m1); % identify which model components corresponds to observed data variables. musclefitobs = {'[plasma glu conc] = plasmagluconc', ... '[glu util] = gluutil'}; % estimate the value of the following parameters: musclefitest = estimatedinfo({'[plasma volume (glu)]', 'k1', 'k2', ... 'vm0', 'vmx', 'km', 'p2u'}); % ensure the parameter estimates are always positive during estimation by % using a log transform on all parameters. [musclefitest.transform] = deal('log'); % fit the data, displaying output at each iteration [musclefitresults, musclefitsim] = sbiofit(m1, fitdata, ... musclefitobs, musclefitest, [], 'nlinfit', fitoptions);
norm of norm of iteration sse gradient step ----------------------------------------------------------- 0 2181.51 1 699.121 16344.7 0.480334 2 426.31 13770.6 0.425703 3 264.226 2415.86 0.351024 4 246.434 1870.42 0.0881693 5 244.478 1356.49 0.0109624 6 243.318 270.056 0.00941789 7 242.955 609.78 0.0694774 8 240.756 1121 0.0481101 9 240.75 916.641 0.000157475 10 240.704 1544.16 7.55918e-05 11 240.435 787.678 0.00407475 12 240.312 693.831 0.00293102 13 240.131 1718.86 0.00869632 14 240.13 258.705 1.58109e-07 15 240.13 498.938 1.64921e-16 iterations terminated: relative norm of the current step is less than options.tolx
plot the change in parameter values, relative to reported values.
figure; musclefitinitvalues = [ get(sbioselect(m1, 'name', 'plasma volume (glu)'), 'value') get(sbioselect(m1, 'name', 'k1'), 'value') get(sbioselect(m1, 'name', 'k2'), 'value') get(sbioselect(m1, 'name', 'vm0'), 'value') get(sbioselect(m1, 'name', 'vmx'), 'value') get(sbioselect(m1, 'name', 'km'), 'value') get(sbioselect(m1, 'name', 'p2u'), 'value') ]; bar(musclefitresults.parameterestimates.estimate ./ musclefitinitvalues - 1); ax = gca; ax.xticklabel = {musclefitest.name}; ylabel('relative change in estimated values'); title('comparing reported and estimated glucose parameter values');
clean up the changes to the model.
plasmainsrule.active = true; gluprodrule.active = true; gluraterule.active = true; plasmainsforcingfcn.active = false; gluprodforcingfcn.active = false; glurateforcingfcn.active = false;
compare the simulation before and after fitting
musclesims = selectbyname([muscleinitsim musclefitsim], ... {'plasma glu conc', 'glu util'}); figure; plot(musclesims(1).time, musclesims(1).data(:,1), '-', ... musclesims(2).time, musclesims(2).data(:,1), '--', ... fitdata.time, fitdata.plasmagluconc, 'x'); xlabel('time (hour)'); ylabel('mg/dl'); legend('initial (simulation)', 'estimated (simulation)', 'experimental'); title('plasma glucose fit');
figure; plot(musclesims(1).time, musclesims(1).data(:,2), '-', ... musclesims(2).time, musclesims(2).data(:,2), '--', ... fitdata.time, fitdata.gluutil, 'x'); xlabel('time (hour)'); ylabel('mg/min'); legend('initial (simulation)', 'estimated (simulation)', 'experimental'); title('glucose utilization fit');
note that significantly increasing some parameters, such as vmx
, allows a much better fit of late-time plasma glucose concentrations.
cleanup
restore warning settings.
warning(warnsettings);
conclusions
simbiology contains several features that facilitate the implementation and simulation of a complex model of the glucose-insulin system. reactions, events, and rules provide a natural way to describe the dynamics of the system. unit conversion allows species and parameters to be specified in convenient units and ensures the dimensional consistency of the model. dose objects are a simple way to describe recurring inputs to a model, such as the daily meal schedule in this example. simbiology also provides built-in support for analysis tasks like simulation and parameter estimation.