Editing reaction kinetics
Previous examples showed how to create models using basico, and using kinetic functions from the reaction database. Here, I want to expand on that showing how to map kinetic functions to reactions involving modifiers as well. Lets start as usual by importing basico:
[1]:
from basico import *
now lets create a new model:
[2]:
new_model(name='Reactions');
we know we can create a reaction, by using the add_reaction
command. It requires at the very least two arguments:
name
: the name of the reactionscheme
: the reaction scheme
If nothing else is specified, this will create the reaction with the given name
and reaction scheme
, assigning it mass action kinetics with local parameters defaulting to a value of 0.1
. All species will be created if they do not exist yet in the model. For example:
[3]:
add_reaction('R1', 'A -> B');
creates the reaction R1
, species A
and B
and a local parameter (R1).k1
. With get_reactions
we can have a look at what was created:
[4]:
get_reactions()[['scheme', 'function', 'mapping']]
[4]:
scheme | function | mapping | |
---|---|---|---|
name | |||
R1 | A -> B | Mass action (irreversible) | {'k1': 0.1, 'substrate': 'A'} |
here I want to point out, the mapping
column. It shows that the parameter k1
is a local one, as it is mapped to a value. And that the substrate of the function is mapped to A
. We can specify the mapping directly in the add_reaction
call, or we can specify it using set_reaction
. So for example, if we wanted to modify the reaction, to map the reactions k1
parameter to a global quantity global_k
, we could to that as follows:
[5]:
add_parameter(name='global_k', initial_value=0.2)
set_reaction('R1', mapping={'k1': 'global_k'})
[6]:
get_reactions()[['scheme', 'function', 'mapping']]
[6]:
scheme | function | mapping | |
---|---|---|---|
name | |||
R1 | A -> B | Mass action (irreversible) | {'k1': 'global_k', 'substrate': 'A'} |
next let us assume, i wanted to use a kinetic from the function database, that includes inhibition for the reaction. Using get_functions
we can filter the functiondatabase, for suitable functions for our reaction, and then filter for ones that contain inhibition:
[7]:
suitable_functions = get_functions(suitable_for='R1')[['formula', 'mapping']]
suitable_inhibitions = suitable_functions[suitable_functions.index.str.contains('inhibition')]
suitable_inhibitions
[7]:
formula | mapping | |
---|---|---|
name | ||
Allosteric inhibition (MWC) | V*(substrate/Ks)*(1+(substrate/Ks))^(n-1)/(L*(... | {'substrate': 'substrate', 'Inhibitor': 'modif... |
Competitive inhibition (irr) | V*substrate/(Km+substrate+Km*Inhibitor/Ki) | {'substrate': 'substrate', 'Inhibitor': 'modif... |
Mixed inhibition (irr) | V*substrate/(Km*(1+Inhibitor/Kis)+substrate*(1... | {'substrate': 'substrate', 'Inhibitor': 'modif... |
Noncompetitive inhibition (irr) | V*substrate/((Km+substrate)*(1+Inhibitor/Ki)) | {'substrate': 'substrate', 'Inhibitor': 'modif... |
Substrate inhibition (irr) | V*substrate/(Km+substrate+Km*(substrate/Ki)^2) | {'substrate': 'substrate', 'Km': 'parameter', ... |
Uncompetitive inhibition (irr) | V*substrate/(Km+substrate*(1+Inhibitor/Ki)) | {'substrate': 'substrate', 'Inhibitor': 'modif... |
let us use Allosteric inhibition (MWC)
here, lets have a look at the formula and the mapping table:
[8]:
as_dict(suitable_inhibitions)[0]
[8]:
{'name': 'Allosteric inhibition (MWC)',
'formula': 'V*(substrate/Ks)*(1+(substrate/Ks))^(n-1)/(L*(1+Inhibitor/Ki)^n+(1+(substrate/Ks))^n)',
'mapping': {'substrate': 'substrate',
'Inhibitor': 'modifier',
'V': 'parameter',
'Ks': 'parameter',
'n': 'parameter',
'L': 'parameter',
'Ki': 'parameter'}}
since this function requires a modifier, we also change the reaction scheme to include a modifier. This is done by adding a semicolon at the end of the reaction scheme, and listing the modifiers space separated there. Then we an assign that function directly.
[9]:
set_reaction('R1', scheme='A -> B; C', function='Allosteric inhibition (MWC)')
get_reactions()[['scheme', 'function', 'mapping']]
[9]:
scheme | function | mapping | |
---|---|---|---|
name | |||
R1 | A -> B; C | Allosteric inhibition (MWC) | {'substrate': 'A', 'Inhibitor': 'C', 'V': 0.1,... |
Note: that here, the mapping is not necessary, as the function has only one modifier, had we multiple modifiers defined, then we’d want to specify the mapping dictionary and map the Inhibitor
to the respective modifier in our reaction scheme:
[10]:
set_reaction('R1', scheme='A -> B; C D', function='Allosteric inhibition (MWC)', mapping={'Inhibitor': 'D'})
get_reactions()[['scheme', 'function', 'mapping']]
[10]:
scheme | function | mapping | |
---|---|---|---|
name | |||
R1 | A -> B; D | Allosteric inhibition (MWC) | {'substrate': 'A', 'Inhibitor': 'D', 'V': 0.1,... |
Note: Assigning a function that uses modifiers, requires that modifiers are present in the reaction scheme, or that all modifiers are specified in the mapping parameter. So assigning the function above would fail with error, if no modifier is declared:
[11]:
add_reaction('error', scheme='A -> B', function='Allosteric inhibition (MWC)');
get_reactions()[['scheme', 'function', 'mapping']]
ERROR:root:the mapping for reaction "error" with function "Allosteric inhibition (MWC)" is not valid and cannot be applied.
[11]:
scheme | function | mapping | |
---|---|---|---|
name | |||
R1 | A -> B; D | Allosteric inhibition (MWC) | {'substrate': 'A', 'Inhibitor': 'D', 'V': 0.1,... |
error | A -> B | Mass action (irreversible) | {'k1': 0.1, 'substrate': 'A'} |
However, it will succeeed, if the modifier is specified. in the mapping parameter:
[12]:
set_reaction('error', new_name='now_it_works', function='Allosteric inhibition (MWC)', mapping={'Inhibitor': 'D'})
get_reactions()[['scheme', 'function', 'mapping']]
[12]:
scheme | function | mapping | |
---|---|---|---|
name | |||
R1 | A -> B; D | Allosteric inhibition (MWC) | {'substrate': 'A', 'Inhibitor': 'D', 'V': 0.1,... |
now_it_works | A -> B; D | Allosteric inhibition (MWC) | {'substrate': 'A', 'Inhibitor': 'D', 'V': 0.1,... |