Initial Setup

library(CoRC)
loadExamples(2)
#> [[1]]
#> # A COPASI model reference:
#> Model name: "Bacterial chemotaxis model"
#> Number of compartments: 1
#> Number of species: 21
#> Number of reactions: 14
species()
#>  [1] "CheA{compartment}"     "CheAp{compartment}"    "CheB{compartment}"    
#>  [4] "CheBp{compartment}"    "CheY{compartment}"     "CheYp{compartment}"   
#>  [7] "CheR{compartment}"     "Tactive{compartment}"  "CheZ{compartment}"    
#> [10] "T0{compartment}"       "T1{compartment}"       "T2{compartment}"      
#> [13] "T3{compartment}"       "T4{compartment}"       "L{compartment}"       
#> [16] "Tactive0{compartment}" "Tactive1{compartment}" "Tactive2{compartment}"
#> [19] "Tactive3{compartment}" "Tactive4{compartment}" "Ttotal{compartment}"

Identifying entities

There are various types of model entities supported for identification by a given string. The strings are matched against the available names of e.g. species, compartments, or global quantities. The fuctions are listed below and return entitiy keys when entities are identified.

species("CheA")
#> [1] "CheA{compartment}"  "CheAp{compartment}"
compartment("comp")
#> [1] "Compartments[compartment]"
quantity("a")
#> character(0)
reaction("Che B phosph")
#> [1] "(Che B phosph)"
parameter("4).kR")
#> [1] "(Rm4).kR"
kinfunction("Michaelis-Menten")
#> [1] "FunctionDB.Functions[Henri-Michaelis-Menten (irreversible)]"
#> [2] "FunctionDB.Functions[Reversible Michaelis-Menten]"
event()
#> character(0)

There are _strict variants that will always return a vector of keys of the same length as the input or throw an error. Accordingly, the behavior for NA or non-uniquely matching strings is to throw an error. This allows the _strict variants to uniquely identify species by giving the full name, when the other methods might then still return multiple matches.

species("CheY")
#> [1] "CheY{compartment}"  "CheYp{compartment}"
species_strict("CheY")
#> [1] "CheY{compartment}"
species_strict("CheYp")
#> [1] "CheYp{compartment}"
species_strict(c("CheY", "CheYp"))
#> [1] "CheY{compartment}"  "CheYp{compartment}"
species_strict("Che")
#> Error in `map2()`:
#>  In index: 1.
#> Caused by error:
#> ! "Che" matches species "CheA{compartment}", "CheAp{compartment}", "CheB{compartment}", "CheBp{compartment}", "CheY{compartment}", "CheYp{compartment}", "CheR{compartment}", "CheZ{compartment}".
species_strict(c(NA, "CheY"))
#> Error: key contains 1 missing values
species_strict("failure")
#> Error: Couldn't match species "failure".

CoRC makes use of the regex functionality of the ‘stringr’ R package. You can therefore wrap any string via regex(string) to enable regex matching.

species(regex("Che.p"))
#> [1] "CheAp{compartment}" "CheBp{compartment}" "CheYp{compartment}"

In cases, where a function argument key is clear to always expect the same kind of entity, identification can also be handled by the function itself. These methods will always use the _strict variants to reliably match species.

getSpecies(key = species("CheY"))$name
#> [1] "CheY"  "CheYp"
getSpecies(key = species_strict("CheY"))$name
#> [1] "CheY"
getSpecies(key = "CheY")$name
#> [1] "CheY"
getSpecies("CheY")$name
#> [1] "CheY"
getSpecies("Che")$name
#> Error in `map2()`:
#>  In index: 1.
#> Caused by error:
#> ! "Che" matches species "CheA{compartment}", "CheAp{compartment}", "CheB{compartment}", "CheBp{compartment}", "CheY{compartment}", "CheYp{compartment}", "CheR{compartment}", "CheZ{compartment}".
getSpecies(species(regex("Che.p")))$name
#> [1] "CheAp" "CheBp" "CheYp"

Using References

The identifying functions can also return value references if specified. Such references identify specific values, of which most COPASI entities can have multiple. This allows to differentiate for example between ‘Concentration’ and ‘Initial Concentration’ of a species. References are needed e.g. for definition of optimization task parameters. They also allow for building expressions, which are needed e.g. in value assignments and the optimization task. Expressions in CoRC behave similar to how they work in COPASI.

species("CheY", reference = "InitialConcentration")
#> [1] "{[CheY]_0}"  "{[CheYp]_0}"

These functions however can not give any clues about what references are available.

species("CheY", reference = "failure")
#> Error in `map2()`:
#>  In index: 1.
#> Caused by error:
#> ! Failed to gather reference "failure".

To help with this, functions implemented to get model values have similar functions that return references instead of values.

str(getSpecies("CheY"))
#> tibble [1 × 13] (S3: tbl_df/tbl/data.frame)
#>  $ key                  : chr "CheY{compartment}"
#>  $ name                 : chr "CheY"
#>  $ compartment          : chr "compartment"
#>  $ type                 : chr "reactions"
#>  $ unit                 : chr "µmol/l"
#>  $ initial_concentration: num 9.7
#>  $ initial_number       : num 8178
#>  $ concentration        : num NaN
#>  $ number               : num NaN
#>  $ rate                 : num 0
#>  $ number_rate          : num 0
#>  $ initial_expression   : chr ""
#>  $ expression           : chr ""
str(getSpeciesReferences("CheY"))
#> tibble [1 × 13] (S3: tbl_df/tbl/data.frame)
#>  $ key                  : chr "CheY{compartment}"
#>  $ name                 : chr "CheY"
#>  $ compartment          : chr "compartment"
#>  $ type                 : chr "reactions"
#>  $ unit                 : chr "µmol/l"
#>  $ initial_concentration: chr "{[CheY]_0}"
#>  $ initial_number       : chr "{CheY.InitialParticleNumber}"
#>  $ concentration        : chr "{[CheY]}"
#>  $ number               : chr "{CheY.ParticleNumber}"
#>  $ rate                 : chr "{CheY.Rate}"
#>  $ number_rate          : chr "{CheY.ParticleNumberRate}"
#>  $ initial_expression   : chr NA
#>  $ expression           : chr NA

Building expressions

Any expression can easily be built as a string. In the following example, several related species are selected via a REGEX rule and the reference to their initial concentration is requested. The expression is then built by concatenating these references with a plus sign. getValue calculates this expressions value and thereby the sum of the individual species.

matching_init_conc <- species(regex("^T[0-4]"), reference = "InitialConcentration")
matching_init_conc
#> [1] "{[T0]_0}" "{[T1]_0}" "{[T2]_0}" "{[T3]_0}" "{[T4]_0}"
expression <- paste0(matching_init_conc, collapse = " + ")
expression
#> [1] "{[T0]_0} + {[T1]_0} + {[T2]_0} + {[T3]_0} + {[T4]_0}"
getValue(expression)
#> [1] 5.3

Using numbers for referencing

Numbers can in principle be used by getting all entities and picking an index from that vector:

species()[5]
#> [1] "CheY{compartment}"
getSpecies(species()[5])$name
#> [1] "CheY"

It is under consideration to allow for a simpler method:

species(5)
#> Error: key is not a string (a length one character vector).
species_strict(5)
#> Error: key is not a character vector
getSpecies(5)$name
#> Error: key is not a character vector

Entity modification

For most kinds of entities there is a finder function (e.g. species), a getter function (e.g. getSpecies) and a setter function (e.g. setSpecies).

Another way to access model values is by evaluating expressions (e.g. getValue):

getSpecies("CheYp")$initial_concentration
#> [1] 0

setSpecies("CheYp", initial_concentration = 1)
getSpecies("CheYp")$initial_concentration
#> [1] 1

yp_init_expression <- species("CheYp", reference = "InitialConcentration")
yp_init_expression
#> [1] "{[CheYp]_0}"
getValue(yp_init_expression)
#> [1] 1