|
363 | 363 | nothing # hide
|
364 | 364 | ```
|
365 | 365 | !!! note
|
366 |
| - If only a single observable is declared, the `begin .. end` block is not required and the observable can be declared directly after the `@observables` option. |
| 366 | + If only a single observable is declared, the `begin ... end` block is not required and the observable can be declared directly after the `@observables` option. |
367 | 367 |
|
368 | 368 | [Metadata](@ref dsl_advanced_options_species_and_parameters_metadata) can be supplied to an observable directly after its declaration (but before its formula). If so, the metadata must be separated from the observable with a `,`, and the observable plus the metadata encapsulated by `()`. E.g. to add a [description metadata](@ref dsl_advanced_options_species_and_parameters_metadata) to our observable we can use
|
369 | 369 | ```@example dsl_advanced_observables
|
@@ -463,3 +463,77 @@ A reaction's metadata can be accessed using specific functions, e.g. `Catalyst.h
|
463 | 463 | rx = @reaction p, 0 --> X, [description="A production reaction"]
|
464 | 464 | Catalyst.getdescription(rx)
|
465 | 465 | ```
|
| 466 | + |
| 467 | +## [Working with symbolic variables and the DSL](@id dsl_advanced_options_symbolics_and_DSL) |
| 468 | +We have previously described how Catalyst represents its models symbolically (enabling e.g. symbolic differentiation of expressions stored in models). While Catalyst utilises this for many internal operation, these symbolic representations can also be accessed and harnessed by the user. Primarily, doing so is much easier during programmatic (as opposed to DSL-based) modelling. Indeed, the section on [programmatic modelling](@ref programmatic_CRN_construction) goes into more details about symbolic representation in models, and how these can be used. It is, however, also ways to utilise these methods during DSL-based modelling. Below we briefly describe two methods for doing so. |
| 469 | + |
| 470 | +### [Using `@unpack` to extract symbolic variables from `ReactionSystem`s](@id dsl_advanced_options_symbolics_and_DSL_unpack) |
| 471 | +Let us consider a simple [birth-death process](@ref basic_CRN_library_bd) created using the DSL: |
| 472 | +```@example dsl_advanced_programmatic_unpack |
| 473 | +using Catalyst # hide |
| 474 | +bd_model = @reaction_network begin |
| 475 | + (p,d), 0 <--> X |
| 476 | +end |
| 477 | +nothing # hide |
| 478 | +``` |
| 479 | +Since we have not explicitly declared `p`, `d`, and `X` using `@parameters` and `@species`, we cannot represent these symbolically (only using `Symbol`s). If we wish to do so, however, we can fetch these into our current scope using the `@unpack` macro: |
| 480 | +```@example dsl_advanced_programmatic_unpack |
| 481 | +@unpack p, d, X = bd_model |
| 482 | +nothing # hide |
| 483 | +``` |
| 484 | +This lists first the quantities we wish to fetch (does not need to be the model's full set of parameters and species), then `=`, followed by the model variable. `p`, `d` and `X` are now symbolic variables in the current scope, just as if they had been declared using `@parameters` or `@species`. We can confirm this: |
| 485 | +```@example dsl_advanced_programmatic_unpack |
| 486 | +X |
| 487 | +``` |
| 488 | +Next, we can now use these to e.g. designate initial conditions and parameter values for model simulations: |
| 489 | +```@example dsl_advanced_programmatic_unpack |
| 490 | +using OrdinaryDiffEq, Plots # hide |
| 491 | +u0 = [X => 0.1] |
| 492 | +tspan = (0.0, 10.0) |
| 493 | +ps = [p => 1.0, d => 0.2] |
| 494 | +oprob = ODEProblem(bd_model, u0, tspan, ps) |
| 495 | +sol = solve(oprob) |
| 496 | +plot(sol) |
| 497 | +``` |
| 498 | + |
| 499 | +!!! warn |
| 500 | + Just like when using `@parameters` and `@species`, `@unpack` will overwrite any variables in the current scope which share name with the imported quantities. |
| 501 | + |
| 502 | +### [Interpolating variables into the DSL](@id dsl_advanced_options_symbolics_and_DSL_interpolation) |
| 503 | +Catalyst's DSL allows Julia variables to be interpolated for the network name, within rate constant expressions, or for species/stoichiometries within reactions. Using the lower-level symbolic interface we can then define symbolic variables and parameters outside of `@reaction_network`, which can then be used within expressions in the DSL. |
| 504 | + |
| 505 | +Interpolation is carried out by pre-appending the interpolating variable with a `$`. For example, here we declare the parameters and species of a birth-death model, and interpolate these into the model: |
| 506 | +```@example dsl_advanced_programmatic_interpolation |
| 507 | +using Catalyst # hide |
| 508 | +t = default_t() |
| 509 | +@species X(t) |
| 510 | +@parameters p d |
| 511 | +bd_model = @reaction_network begin |
| 512 | + ($p, $d), 0 <--> $X |
| 513 | +end |
| 514 | +``` |
| 515 | +Additional information (such as default values or metadata) supplied to `p`, `d`, and `X` is carried through to the DSL. However, interpolation for this purpose is of limited value, as such information [can be declared within the DSL](@ref dsl_advanced_options_declaring_species_and_parameters). However, it is possible to interpolate larger algebraic expressions into the DSL, e.g. here |
| 516 | +```@example dsl_advanced_programmatic_interpolation |
| 517 | +@species X1(t) X2(t) X3(t) E(t) |
| 518 | +@parameters d |
| 519 | +d_rate = d/(1 + E) |
| 520 | +degradation_model = @reaction_network begin |
| 521 | + $d_rate, X1 --> 0 |
| 522 | + $d_rate, X2 --> 0 |
| 523 | + $d_rate, X3 --> 0 |
| 524 | +end |
| 525 | +``` |
| 526 | +we declare an expression `d_rate`, which then can be inserted into the DSL via interpolation. |
| 527 | + |
| 528 | +It is also possible to use interpolation in combination with the `@reaction` macro. E.g. the reactions of the above network can be declared individually using |
| 529 | +```@example dsl_advanced_programmatic_interpolation |
| 530 | +rxs = [ |
| 531 | + @reaction $d_rate, $X1 --> 0 |
| 532 | + @reaction $d_rate, $X2 --> 0 |
| 533 | + @reaction $d_rate, $X3 --> 0 |
| 534 | +] |
| 535 | +nothing # hide |
| 536 | +``` |
| 537 | + |
| 538 | +!!! note |
| 539 | + When using interpolation, expressions like `2$spec` won't work; the multiplication symbol must be explicitly included like `2*$spec`. |
0 commit comments