main content

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

  1. 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.

  2. 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 (named insulin 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 to dimensionless.)

  • setting the configuration set timeunits to hour, 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

figure contains 6 axes objects. axes object 1 with title plasma glu conc, xlabel time (hour), ylabel milligram/deciliter contains 2 objects of type line. axes object 2 with title plasma ins conc, xlabel time (hour), ylabel picomole/liter contains 2 objects of type line. axes object 3 with title glu prod, xlabel time (hour), ylabel milligram/minute contains 2 objects of type line. these objects represent normal, diabetic. axes object 4 with title glu appear rate, xlabel time (hour), ylabel milligram/minute contains 2 objects of type line. axes object 5 with title glu util, xlabel time (hour), ylabel milligram/minute contains 2 objects of type line. axes object 6 with title ins secr, xlabel time (hour), ylabel picomole/minute contains 2 objects of type line.

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

figure contains 6 axes objects. axes object 1 with xlabel time (hour) contains an object of type line. this object represents normal. axes object 2 with title plasma glu conc, xlabel time (hour) contains 2 objects of type line. these objects represent -ins =\beta, -ins  \beta. axes object 3 with xlabel time (hour) contains 2 objects of type line. these objects represent =ins -\beta,  ins -\beta. axes object 4 with xlabel time (hour) contains an object of type line. this object represents normal. axes object 5 with title plasma ins conc, xlabel time (hour) contains 2 objects of type line. these objects represent -ins =\beta, -ins  \beta. axes object 6 with xlabel time (hour) contains 2 objects of type line. these objects represent =ins -\beta,  ins -\beta.

note that either low insulin sensitivity (dashed green line, -ins=β) or low beta-cell sensitivity (dashed-dotted cyan line, =ins-β) 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, -ins β) 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);

figure optimization plot function contains an axes object. the axes object with title current function value: 1.6491, xlabel iteration, ylabel function value contains a line object which displays its values using only markers.

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');

figure contains an axes object. the axes object with title glucose appearance fit, xlabel time (hour), ylabel mg/min contains 4 objects of type line. one or more of the lines displays its values using only markers these objects represent reported, estimated (nlinfit), estimated (fminunc), experimental.

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')

figure contains an axes object. the axes object with title comparing reported and estimated gastrointestinal parameter values, ylabel relative change in estimated values contains 2 objects of type bar. these objects represent nlinfit, fminunc.

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');

figure contains an axes object. the axes object with title comparing reported and estimated glucose parameter values, ylabel relative change in estimated values contains an object of type bar.

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 contains an axes object. the axes object with title plasma glucose fit, xlabel time (hour), ylabel mg/dl contains 3 objects of type line. one or more of the lines displays its values using only markers these objects represent initial (simulation), estimated (simulation), experimental.

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');

figure contains an axes object. the axes object with title glucose utilization fit, xlabel time (hour), ylabel mg/min contains 3 objects of type line. one or more of the lines displays its values using only markers these objects represent initial (simulation), estimated (simulation), experimental.

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.

网站地图