ctl.ControlSBML

controlSBML provides ways to use an SBML model to construct an object representing a system model that can be used by the control package. Two kinds of control objects can be constructed. The first, control.NonlinearIOSystem, wraps an entire nonlinear SBML model. This allows the control package to do the same kind of detailed simulations that are provided by SBML simulators as as libroadrunner and Copasi. The second object, control.StateSpace, provides a linear approximation to the SBML model. control.NonlinearIOSystem and control.StateSpace objects are constructed from an ctl.ControlSBML object.

In the sequel, we use the following Antiimony representation of an SBML model.

1SIMPLE_MODEL = """
2    species E1;
3    J1: S1 -> S2; S1 + E1
4    S1 = 10; S2 = 0; E1 = 1;
5"""

Constructors

We begin with constructing a ctl.ControlSBML object. This requires having a representation of an SBML model. This can be an XML file, an XML URL, an antimony file, or a libroadrunner object. We refer to any of these representations of the SBML model as a model reference. The following constructs ctl.ControlSBML object for this model.

ctlsb = ctl.ControlSBML(SIMPLE_MODEL)

This object has a number of useful properties.

  • ctlsb.antimony is the Antimony string that corresponds to the model reference in the constructor.

  • ctlsb.roadrunner is the libroadrunner object for the model reference in the constructor.

  • ctlsb.state_ser is a pandas Series that provides the values of the concentrations of floating species (the state variables).

  • ctlsb.setTime(time) runs the simulation from time 0 to a desired time. This updates ctlsb.state_ser.

To create an object that is more useful for control analysis, you should specify at least one input and at least one output. An input is a chemical species that can be manipulated by increasing or decreasing its value. An output is a chemical species or reaction flux that can be read. An example of this constructor is:

ctlsb = ctl.ControlSBML(SIMPLE_MODEL,
    input_names=["E1"], output_names=["S2"])

Note that both input_names and output_names are lists of strings. Inputs and outputs must be specified to make use of subsequent capabilities of ctl.ControlSBML.

control.NonlinearIOSystem

The method ctl.ControlSBML.makeNonlinearIOSystem constructs a control.NonlinearIOSystem object for an SBML model. The control.NonlinearIOSystem object provides a way to use many of the capabilities of the control system library. For example,

ctlsb = ctl.ControlSBML(SIMPLE_MODEL,
        input_names=["E1"], output_names=["S1", "S2"])
sys = ctlsb.makeNonlinearIOSystem("simple")

sys is a control.NonlinearIOSystem object, and the following simulates this system for 5 s.

times = [0.1*n for n in range(51)]
time_response = control.input_output_response(sys,
    times, X0=ctl.makeStateVector(sys))

ctlsb is constructed to have the input E1 and the outputs S1 and S2. sys is a control.NonlinearIOSystem object that wraps the SBML model. time_response is a control.TimeResponseData object. The simulation requires knowlege of initial values for all state variables, which is provided by the method ctl.makeStateVector.

Going a bit further, we introduce a plotting function for the control.TimeResponseData object.

 1def plotTimeResponse(time_response, output_names,
 2      is_legend=True, stmts=None):
 3    # Plots the results of running a simulation
 4    outputs = time_response.outputs
 5    times = time_response.time
 6    colors = ["orange", "green"]
 7    for idx in range(len(output_names)):
 8        if np.ndim(outputs) > 1:
 9            plt.plot(times, outputs[idx,:], c=colors[idx])
10        else:
11            plt.plot(times, outputs, c=colors[idx])
12    if is_legend:
13        _ = plt.legend(output_names)
14    if stmts is None:
15        stmts = []
16    for stmt in stmts:
17        exec(stmt)
18    plt.xlabel("time")
19    plt.ylabel("concentration")

We execute the statement below to plot the simulation results.

plotTimeResponse(time_response, ["S1", "S2"])
_images/simple_model_plot.png

control.StateSpace

A state space model is a linear system of differential equations in which there are \(n\) states, \(p\) inputs, and \(q\) outputs.

\[\begin{split}\dot{\bf x} &= {\bf A} {\bf x} + {\bf B} {\bf u} \\ {\bf y} &= {\bf C} {\bf x}\end{split}\]

where:

\[\begin{split}{\bf x} \text{ has dimension } n \times 1 \\ {\bf u} \text{ has dimension } p \times 1 \\ {\bf y} \text{ has dimension } q \times 1 \\ {\bf A} \text{ has dimension } n \times n \\ {\bf B} \text{ has dimension } n \times p \\ {\bf C} \text{ has dimension } q \times p \\\end{split}\]

\({\bf x}\) is the state variable, \({\bf u}\) is the input vector, and \({\bf y}\) is the output.

controlSBML constructs a control.StateSpace object for an SBML model as follows. The state variables are floating species. The \({\bf u}\) are names of floating species that are manipulated inputs (input_names). The \({\bf y}\) are the names of measured outputs (output_names), either floating species or names of reactions whose fluxes are output. A linear approximation for an SBML model is constructed using the Jacobian of the state variables at a specified operating point. The operating point is a simulation time at which state variables are assigned their values to calculate the Jacobian.

Once a ctl.ControlSBML object has been constructed, the method makeStateSpace is used to create a control.StateSpace object. This is illustrated below to construct a control.StateSpace object using time 0 as the operating point.

ctlsb = ctl.ControlSBML(SIMPLE_MODEL,
    input_names=["S1"], output_names=["S2"])
state_space = ctlsb.makeStateSpace(time=0)

The resulting state space model is represented below. \({\bf x}\) is a 3 dimensional vector that correspond to the state variables (floating species) E1, S1, and S2. \(u\) and \(y\) are scalars (and so are not in bold). \({\bf A}\) is in the upper left; \({\bf B}\) is in the upper right; and \({\bf C}\) is in the lower left. \({\bf A}\) is A \(3 \times 3\) matrix; \({\bf B}\) is a \(3 \times 1\) matrix; and \({\bf C}\) is \(1 \times 3\).

_images/state_space_matrix.png

We can construct a transfer function from a control.StateSpace object. The transfer function for the above system is obtained by

transfer_function = control.tf(state_space)

and is displayed as

_images/transfer_function1.png

The DC gain for this transfer function is \(\infty\). This makes sense since by having a unti input for times \(\geq 0\) and a single reaction that consumes S1 to produce S2, the output increases without bound.

Now consider a slightly different reaction network.

 1model = """
 2    J1: S1 -> S2; S1
 3    J2: S2 -> S1; S2
 4    J3: S2 -> ; k*S2
 5    S1 = 10; S2 = 0;
 6    k = 0.8
 7"""
 8
 9ctlsb = ctl.ControlSBML(model,
10      input_names=["S1"], output_names=["S2"])
11state_space = ctlsb.makeStateSpace()

The state space matrices are:

_images/state_space2.png

We simulate and plot the response of the state space model to a unit step in the input in S1.

1times = [0.1*n for n in range(301)]
2ss_time_response = control.forced_response(state_space,
3      times, X0=[10, 0], U=1)
4plotTimeResponse(ss_time_response, ["S2"], is_legend=False)
5plt.plot([0, 30], [1.25, 1.25], linestyle="--")
_images/step_response2.png

The transfer function is

_images/transfer_function2.png

and so the DC gain is \(1/0.8=1.25\), which is consistent with the plot.