4. Handling multiple experiments¶
The INCAWrapper can create a model with data from multiple experiments. This is relevant when you wish to fit data from a parallel labelling experiment. The toy model example, which have worked with has two experiments. We will return the the simple toy model [1,2] that we also used in the Quick start guide (ref: ). In this notebook we will assume that you are familiar with the dataset, if not please refer to the quick start guide.
First, we will import the required python packages and the data.
[1]:
import pandas as pd
import pathlib
import incawrapper
import ast
[2]:
data_folder = pathlib.Path("./examples/Literature data/simple model")
tracers_data = pd.read_csv(data_folder / "tracers.csv",
converters={'atom_mdv':ast.literal_eval, 'atom_ids':ast.literal_eval} # a trick to read lists from csv
)
reactions_data = pd.read_csv(data_folder / "reactions.csv")
flux_data = pd.read_csv(data_folder / "flux_measurements.csv")
ms_data = pd.read_csv(data_folder / "ms_measurements.csv",
converters={'labelled_atom_ids': ast.literal_eval} # a trick to read lists from csv
)
We will take a closer look at the MS data.
[3]:
ms_data
[3]:
experiment_id | met_id | ms_id | measurement_replicate | labelled_atom_ids | unlabelled_atoms | mass_isotope | intensity | intensity_std_error | time | |
---|---|---|---|---|---|---|---|---|---|---|
0 | exp1 | F | F1 | 1 | [1, 2, 3] | NaN | 0 | 0.0001 | 0.000002 | 0 |
1 | exp1 | F | F1 | 1 | [1, 2, 3] | NaN | 1 | 0.8008 | 0.016016 | 0 |
2 | exp1 | F | F1 | 1 | [1, 2, 3] | NaN | 2 | 0.1983 | 0.003966 | 0 |
3 | exp1 | F | F1 | 1 | [1, 2, 3] | NaN | 3 | 0.0009 | 0.000018 | 0 |
4 | exp2 | F | F1 | 1 | [1, 2, 3] | NaN | 0 | 0.0002 | 0.000002 | 0 |
5 | exp2 | F | F1 | 1 | [1, 2, 3] | NaN | 1 | 0.7008 | 0.016016 | 0 |
6 | exp2 | F | F1 | 1 | [1, 2, 3] | NaN | 2 | 0.1800 | 0.003966 | 0 |
7 | exp2 | F | F1 | 1 | [1, 2, 3] | NaN | 3 | 0.0009 | 0.000018 | 0 |
We see that this data holds measurements of the ms_id (or ms fragment) from two different experiments, exp1 and exp2. If we have a closer look at the tracers data, we see that also this describes two labelling experiments.
[4]:
tracers_data
[4]:
experiment_id | met_id | tracer_id | atom_ids | ratio | atom_mdv | enrichment | |
---|---|---|---|---|---|---|---|
0 | exp1 | A | [2-13C]A | [2] | 1.0 | [0, 1] | 1 |
1 | exp2 | A | [1,2-13C]A | [1, 2] | 0.5 | [0.05, 0.95] | 1 |
To create an INCAScript with data from parallel labelling experiments simply specify the experiments in the experiment_id
argument of the create_inca_script_from_data
function.
[5]:
incascript = incawrapper.create_inca_script_from_data(
reactions_data=reactions_data,
tracer_data=tracers_data,
flux_measurements=flux_data,
ms_measurements=ms_data,
experiment_ids=["exp1", "exp2"])
Now, we simply need to specify the options and which algorithms to run.
[6]:
OUTPUT_FILE = data_folder / "simple_model_inca_multiple_exp.mat"
incascript.add_to_block('options', incawrapper.define_options(fit_starts=20, sim_na=False))
incascript.add_to_block('runner', incawrapper.define_runner(OUTPUT_FILE, run_estimate=True))
We can now run the INCAScript in INCA.
[7]:
import dotenv
inca_directory = dotenv.get_key(dotenv.find_dotenv(), "INCA_base_directory")
incawrapper.run_inca(incascript, INCA_base_directory=inca_directory)
INCA script saved to /var/folders/z6/mxpxh4k56tv0h0ff41vmx7gdwtlpvp/T/tmptjx2o4yi/inca_script.m.
Starting MATLAB engine...
ms_exp1 = 1x1 msdata object
fields: atoms id [idvs] more on state
F1
ms_exp2 = 1x1 msdata object
fields: atoms id [idvs] more on state
F1
m = 1x1 model object
fields: [expts] [mets] notes [options] [rates] [states]
5 reactions (6 fluxes)
6 states (3 balanced, 1 source, 2 sink and 0 unbalanced)
6 metabolites
2 experiments
Directional
Iteration Residual Step-size derivative Lambda
0 1.00011e+12
1 9.9892e+11 0.000816 -7.59e+11 11092.6
2 9.93976e+11 0.00261 -9.48e+11 11092.6
3 1.63688e+08 1 -2.36e+09 11092.6
4 8.05725e+07 1 -8.95e+06 3697.54
5 4.49334e+07 1 -7.75e+06 3697.52
6 1.97489e+06 1 -4.87e+06 3702.93
7 333142 1 -2.3e+05 1234.31
8 219695 0.461 9.67e+03 467.291
9 218299 1 -135 467.291
10 218282 1 -1.21 155.764
11 218278 1 -1.4 51.9212
12 218274 1 -1.52 23.8274
13 218273 1 -0.596 18.4177
14 218272 1 -0.144 16.1011
15 218272 1 -0.0254 14.7826
16 218272 1 -0.00321 13.9138
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 1.00006e+12
1 3.66313e+11 0.424 -5.62e+11 2378.16
2 5.03442e+08 1 -2.19e+08 2378.16
3 8.87602e+07 1 -7.43e+07 792.722
4 1.7878e+07 0.597 -3.39e+07 577.383
5 1.25416e+06 1 -2.06e+06 577.383
6 332121 0.524 -3.21e+05 207.606
7 223783 1 -1.38e+03 207.606
8 218282 1 -228 140.037
9 218272 1 -0.407 46.679
10 218272 1 0.0116 15.5597
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.98914e+11
1 8.03687e+11 0.103 -8.96e+11 21.8353
2 5.53648e+11 0.17 -6.67e+11 21.8353
3 1.80273e+06 1 -1.65e+05 21.8353
4 218636 0.864 2.69e+03 7.27843
5 218636 1 -2.9e-14 7.27843
6 218641 1 18.6 2.42614
7 218267 1 -9.02 4.85228
8 218234 1 -65 1.61743
9 218202 0.00542 -3.97e+03 0.539143
10 215967 1 -604 0.539143
11 215785 1 21.4 0.179714
12 215783 1 -0.00838 0.0599047
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 1.00015e+12
1 9.957e+11 0.00206 -1.06e+12 3074.53
2 1.32455e+11 0.636 -3.62e+11 3074.53
3 1.20967e+08 1 -1.26e+07 3074.53
4 7.30668e+07 1 -4.67e+06 1024.84
5 4.55129e+07 1 -8.15e+06 1033.96
6 1.23514e+06 1 -3.61e+06 1048.93
7 269645 1 -1.29e+05 349.643
8 218283 0.248 3.15e+03 166.589
9 218283 1 -0.0029 166.589
10 218280 1 -1.52 55.5297
11 218275 1 -1.78 23.8023
12 218273 1 -0.688 18.4841
13 218272 1 -0.166 16.1809
14 218272 1 -0.0289 14.8654
15 218272 1 -0.00366 14.0006
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99668e+11
1 9.99403e+11 0.000134 -9.89e+11 989.259
2 3.90446e+08 1 -9.46e+09 989.259
3 1.15796e+08 0.482 -1.9e+08 329.753
4 1.82915e+07 1 -1.38e+07 329.753
5 1.58109e+06 1 -2.4e+06 224.065
6 223862 0.998 1.43e+04 96.3312
7 218286 1 -131 96.3312
8 218277 1 -2.22 32.1104
9 218273 1 -1.37 18.0557
10 218272 1 -0.33 15.864
11 218272 1 -0.0586 14.5548
12 218272 1 -0.00799 13.6817
13 218272 1 -0.00127 13.2237
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.9943e+11
1 6.68424e+11 0.182 -8.17e+11 3.21808
2 1.87869e+11 0.47 -3.54e+11 3.21808
3 1.33336e+11 0.158 -1.58e+11 3.21808
4 216760 1 -56.9 3.21808
5 216607 1 1.69e+03 1.07269
6 215793 1 114 1.42053
7 215783 1 -0.103 0.47351
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.9975e+11
1 5.89693e+10 0.757 -2.43e+11 1.65671
2 4.82847e+10 0.0951 -5.34e+10 1.65671
3 215789 1 31.3 1.65671
4 215783 1 0.0483 0.552238
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99289e+11
1 9.8052e+11 0.00947 -9.85e+11 310.855
2 7.64919e+11 0.117 -8.66e+11 310.855
3 1.1266e+07 1 -2.44e+05 310.855
4 1.01649e+06 1 -1.37e+06 103.618
5 218636 0.641 2.27e+03 44.6771
6 218636 1 1.19e-12 44.6771
7 218633 1 -0.83 14.8924
8 218274 1 -3 14.0827
9 218274 1 4.43 4.69424
10 218278 1 9.52 8.55709
11 218272 1 0.999 17.1142
12 218272 1 -0.0579 17.7615
13 218272 1 -0.0135 15.7441
14 218272 1 -0.0023 14.6123
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.98465e+11
1 9.98081e+11 0.000192 -9.98e+11 3.55785
2 4.39155e+11 0.337 -6.62e+11 3.55785
3 1.82393e+11 0.356 -2.83e+11 3.55785
4 216931 1 -140 3.55785
5 216786 1 2.23e+03 1.18595
6 215799 1 159 1.68044
7 215783 1 -0.193 0.560146
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99765e+11
1 1.92326e+11 0.562 -4.38e+11 2.0233
2 1.91479e+11 0.00221 -1.92e+11 2.0233
3 8.32093e+10 0.341 -1.26e+11 2.0233
4 216701 1 -5.05 2.0233
5 216406 1 1.17e+03 0.674434
6 215789 1 71 0.705201
7 215783 1 -0.0423 0.235067
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99899e+11
1 9.98157e+11 0.000878 -9.83e+11 2515.61
2 9.78418e+11 0.00999 -9.83e+11 2515.61
3 9.01127e+07 1 -4.85e+07 2515.61
4 3.39939e+07 1 -1.06e+07 838.535
5 1.29494e+07 1 -5.86e+06 825.974
6 992503 1 -1.58e+06 814.407
7 247559 1 -9.17e+04 271.469
8 218419 0.151 2.24e+03 148.475
9 218283 1 -4.8 148.475
10 218279 1 -1.67 49.4915
11 218274 1 -1.77 20.7268
12 218273 1 -0.539 17.276
13 218272 1 -0.112 15.5075
14 218272 1 -0.0175 14.4234
15 218272 1 -0.00193 13.6787
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99948e+11
1 9.95476e+11 0.0176 -1.26e+11 14170.5
2 9.33367e+11 0.0319 -9.58e+11 14170.5
3 1.78885e+07 1 -3.3e+07 14170.5
4 957403 1 -1.5e+06 4723.5
5 223891 0.862 1.04e+04 1574.5
6 223891 1 -1.03e-13 1574.5
7 223887 1 -2.24 524.834
8 218289 1 -230 174.945
9 218277 1 -1.2 58.3148
10 218272 1 -1.69 19.4383
11 218270 1 -0.695 14.9738
12 218269 1 -0.226 12.8761
13 218269 1 -0.122 11.368
14 218269 1 -0.211 8.39338
15 218267 1 -1.53 2.79779
16 218235 0.56 -108 0.932597
17 217272 1 -464 0.932597
18 216013 1 1.07e+03 0.310866
19 215783 1 -9.34 0.208332
20 215783 1 -0.000984 0.0694441
Optimization terminated: Constrained optimum found.
Norm of gradient less than tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99712e+11
1 2.49174e+11 0.501 -4.99e+11 2.04418
2 3.61841e+10 0.619 -9.5e+10 2.04418
3 218283 1 -2.34 2.04418
4 218566 1 432 0.681393
5 218286 1 76.3 1.36279
6 218255 1 -8.97 5.45114
7 218220 0.388 -85.2 4.814
8 217833 1 -194 4.814
9 216110 1 1.59e+03 1.60467
10 215784 1 -14.3 1.0845
11 215783 1 -0.00214 0.361499
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99801e+11
1 9.98764e+11 0.000519 -9.99e+11 1.25553
2 2.00099e+11 0.552 -4.47e+11 1.25553
3 218188 1 -24 1.25553
4 215795 1 -78.9 0.418511
5 215783 1 -0.0467 0.139504
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99817e+11
1 9.37347e+11 0.0318 -9.65e+11 7.98547
2 2.40844e+11 0.493 -4.75e+11 7.98547
3 4.92392e+09 0.857 -3.44e+10 7.98547
4 223891 1 -0.000188 7.98547
5 224272 1 771 2.66182
6 218364 1 160 5.32365
7 218283 0.0219 2.11e+03 1.77455
8 218283 1 -9.89e-05 1.77455
9 220062 1 1.91e+03 0.591516
10 218685 1 481 1.18303
11 218278 1 16.4 4.73213
12 218283 0.432 49.7 6.89174
13 218283 0.853 25.4 13.7835
14 218272 1 -1.46 55.1339
15 218271 1 -0.165 53.4536
16 218271 1 -0.082 36.1201
17 218271 1 -0.0323 29.0984
18 218271 1 -0.0178 22.8463
19 218271 1 -0.0196 14.9489
20 218271 1 -0.0668 4.98295
21 218270 1 -0.366 1.66098
22 218262 0.879 -25.5 0.553662
23 217910 1 -175 0.553662
24 216395 1 2.51e+03 0.184554
25 215786 1 -36.1 0.170442
26 215783 1 -0.0149 0.056814
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99608e+11
1 9.93827e+11 0.00293 -9.82e+11 642.848
2 9.13486e+11 0.0413 -9.53e+11 642.848
3 2.9785e+07 1 -1.05e+06 642.848
4 5.08379e+06 1 -4.65e+06 214.283
5 340619 1 -3.79e+05 152.098
6 220168 0.474 1.13e+04 50.6995
7 218283 1 -23.9 50.6995
8 218274 1 -2.68 16.8998
9 218272 1 -0.56 15.3559
10 218272 1 -0.0916 14.2157
11 218272 1 -0.0119 13.4348
12 218272 1 -0.00179 12.9736
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99081e+11
1 9.57214e+11 0.0212 -9.76e+11 161.605
2 5.93691e+11 0.212 -7.54e+11 161.605
3 6.82208e+06 1 -4.23e+05 161.605
4 459048 1 -5.88e+05 53.8682
5 219043 0.485 8.75e+03 17.9561
6 218283 1 -3.47 17.9561
7 218274 1 8.29 5.98535
8 218283 0.825 20.8 6.68111
9 218274 1 4.51 13.3622
10 218272 1 -0.489 22.1106
11 218272 1 -0.185 17.5589
12 218272 1 -0.0476 15.2878
13 218271 1 -0.0104 13.8866
14 218271 1 -0.00469 13.0898
15 218271 1 -0.00807 7.35136
16 218271 1 -0.0279 2.45045
17 218271 1 -0.117 0.816818
18 218283 0.559 22.2 0.272273
19 218283 1 12.1 0.544545
20 218272 1 0.749 2.17818
21 218271 1 -0.0125 17.4255
22 218271 1 -0.0085 15.9479
23 218271 1 -0.0266 5.31595
24 218271 1 -0.109 1.77198
25 218271 1 0.676 0.590661
26 218271 1 0.128 1.18132
27 218278 1 9.16 1.43809
28 218271 1 1.91 2.87618
29 218270 1 -0.112 11.5047
30 218270 1 -0.0442 11.0262
31 218270 1 -0.0683 8.22184
32 218270 1 -0.326 2.74061
33 218262 1 -12.4 0.913537
34 218210 0.101 -720 0.304512
35 215827 1 -332 0.304512
36 215783 1 1.51 0.101504
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99678e+11
1 1.54239e+11 0.607 -3.93e+11 1.65476
2 5.06518e+10 0.427 -8.84e+10 1.65476
3 215799 1 18.1 1.65476
4 215783 1 0.221 0.551587
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 9.99405e+11
1 8.93971e+11 0.0543 -9.44e+11 29.6553
2 1.26182e+06 1 1.37e+05 29.6553
3 501774 0.308 -7.99e+05 9.88511
4 223891 0.459 1.3e+04 9.88511
5 223891 1 1.83e-11 9.88511
6 224078 1 510 3.29504
7 218330 1 108 6.59007
8 218283 0.0337 1.11e+03 2.19669
9 218283 1 -0.000101 2.19669
10 219516 1 1.35e+03 0.73223
11 218547 1 329 1.46446
12 218275 1 9.01 5.85784
13 218283 0.757 23 6.69557
14 218274 1 5.82 13.3911
15 218273 1 -0.634 24.7046
16 218272 1 -0.283 18.5188
17 218272 1 -0.0779 15.8213
18 218272 1 -0.0162 14.3171
19 218272 1 -0.00447 13.5168
20 218272 1 -0.00423 11.2605
21 218271 1 -0.0138 3.7535
22 218271 1 -0.055 1.25117
23 218271 1 -0.525 0.417056
24 218267 0.353 -57.5 0.139019
25 217159 1 -525 0.139019
26 215979 1 931 0.0463396
27 215783 1 -7.43 0.0293745
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 1.00001e+12
1 9.99085e+11 0.000656 -6.9e+11 1589.63
2 9.91318e+11 0.00396 -9.78e+11 1589.63
3 4.70869e+07 1 -2.43e+08 1589.63
4 1.20563e+07 1 -7.33e+06 529.877
5 1.60046e+06 1 -1.92e+06 467.529
6 295989 1 -1.76e+05 274.491
7 218630 0.346 6.09e+03 114.756
8 218283 1 -9.63 114.756
9 218278 1 -2 38.252
10 218274 1 -1.5 22.2691
11 218273 1 -0.525 17.8415
12 218272 1 -0.119 15.7951
13 218272 1 -0.0198 14.5891
14 218272 1 -0.00237 13.7768
Optimization terminated: Constrained optimum found.
Parameters converged to within tolerance.
Directional
Iteration Residual Step-size derivative Lambda
0 215783
1 10086.4 1 -1.63e-05 9.93117e-05
Optimization terminated: Constrained optimum found.
Norm of gradient less than tolerance.
Estimation completed in 13.1800 seconds.
Preprocessing time: 7.5600 s
Computation time: 5.4600 s
Postprocessing time: 0.1600 s
Warning: Network is ill-conditioned.
Simulation completed in 0.1100 seconds.
Preprocessing time: 0.0900 s
Computation time: 0.0100 s
Postprocessing time: 0.0100 s
--- 23.830405950546265 seconds -
Finally, the results can be imported to python using the INCAResults
as usual.
[8]:
res = incawrapper.INCAResults(OUTPUT_FILE)
And one can inspect the results and analyze it as any other data.
[9]:
res.fitdata.fitted_parameters
[9]:
type | id | eqn | val | std | lb | ub | unit | free | alf | chi2s | cont | cor | cov | vals | base | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Net flux | R1 | A -> B | 1.000000e+01 | 0.000010 | [] | [] | [] | 0 | 0.05 | [] | 1 | [1.0, 0.00010674352435121925, 0.0, 5.286525244... | [9.999999960041972e-11, 6.687822951684241e-11,... | [] | {'id': []} |
1 | Net flux | R2 net | B <-> D | 6.687824e+00 | 0.062653 | [] | [] | [] | 1 | 0.05 | [] | 1 | [0.0001067435188136774, 1.0, 0.0, -0.999999987... | [6.687822604739546e-11, 0.003925422983263398, ... | [] | {'id': []} |
2 | Exch flux | R2 exch | B <-> D | 1.000000e-07 | 0.000000 | [] | [] | [] | 1 | 0.05 | [] | 1 | [0, 0, 1, 0, 0, 0, 0, 0] | [0, 0, 0, 0, 0, 0, 0, 0] | [] | {'id': []} |
3 | Net flux | R3 | B -> C + E | 1.656088e+00 | 0.031327 | [] | [] | [] | 1 | 0.05 | [] | 1 | [5.2865257985399465e-05, -0.9999999872625187, ... | [1.656088677651213e-11, -0.0019627114581925844... | [] | {'id': []} |
4 | Net flux | R4 | B + C -> D + E + E | 1.656088e+00 | 0.031327 | [] | [] | [] | 0 | 0.05 | [] | 1 | [5.2865257985399465e-05, -0.9999999872625187, ... | [1.656088677651213e-11, -0.0019627114581925844... | [] | {'id': []} |
5 | Net flux | R5 | D -> F | 8.343912e+00 | 0.031327 | [] | [] | [] | 0 | 0.05 | [] | 1 | [0.0002663522874548933, 0.9999999872625207, 0.... | [8.343911282390759e-11, 0.001962711525070814, ... | [] | {'id': []} |
6 | Norm | exp1 F1 exp1_F1_0_0_1 norm | [] | 9.990001e-01 | 0.016498 | [] | [] | [] | 1 | 0.05 | [] | 0 | [-1.9715049512208566e-12, 0.5164103260129809, ... | [-3.2526065174565133e-19, 0.000533791685561596... | [] | {'id': []} |
7 | Norm | exp2 F1 exp2_F1_0_0_1 norm | [] | 9.523818e-02 | 0.000892 | [] | [] | [] | 1 | 0.05 | [] | 0 | [7.718240171440117e-13, 3.4992380087242814e-08... | [6.888177722179846e-21, 1.9566032458283252e-12... | [] | {'id': []} |
4.1. References¶
[1] M. R. Antoniewicz, J. K. Kelleher, and G. Stephanopoulos, “Determination of confidence intervals of metabolic fluxes estimated from stable isotope measurements,” Metabolic Engineering, vol. 8, no. 4, pp. 324–337, Jul. 2006, doi: 10.1016/j.ymben.2006.01.004.
[2] M. R. Antoniewicz, J. K. Kelleher, and G. Stephanopoulos, “Elementary metabolite units (EMU): A novel framework for modeling isotopic distributions,” Metabolic Engineering, vol. 9, no. 1, pp. 68–86, Jan. 2007, doi: 10.1016/j.ymben.2006.09.001.