Skip to content

Commit a668cc6

Browse files
committed
up
1 parent a0bf4ef commit a668cc6

File tree

2 files changed

+108
-19
lines changed

2 files changed

+108
-19
lines changed

src/reaction_network.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,9 @@ function read_observed_options(options, species_declared)
719719
ivs_get_expr = :(unique(reduce(vcat,[arguments(ModelingToolkit.unwrap(dep)) for dep in $dependants])))
720720
push!(observed_vars.args, :($obs_name = $(obs_name)($(ivs_get_expr)...)))
721721
end
722+
723+
# If nothing was added to `observed_vars`, it has to be modified not to throw an error.
724+
(length(observed_vars.args) == 1) && (observed_vars = :())
722725
else
723726
# If option is not used, return empty expression and vector.
724727
observed_vars = :()

test/dsl/dsl_options.jl

Lines changed: 105 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,49 @@ let
387387
@test plot(sol; idxs=[:X, :Y]).series_list[2].plotattributes[:y][end] 3.0
388388
end
389389

390+
# Compares programmatic and DSL system with observables.
391+
let
392+
# Model declarations.
393+
rn_dsl = @reaction_network rn_observed begin
394+
@observables begin
395+
X ~ x + 2x2y
396+
Y ~ y + x2y
397+
end
398+
k, 0 --> (x, y)
399+
(kB, kD), 2x + y <--> x2y
400+
d, (x,y,x2y) --> 0
401+
end
402+
403+
@variables t X(t) Y(t)
404+
@species x(t), y(t), x2y(t)
405+
@parameters k kB kD d
406+
r1 = Reaction(k, nothing, [x], nothing, [1])
407+
r2 = Reaction(k, nothing, [y], nothing, [1])
408+
r3 = Reaction(kB, [x, y], [x2y], [2, 1], [1])
409+
r4 = Reaction(kD, [x2y], [x, y], [1], [2, 1])
410+
r5 = Reaction(d, [x], nothing, [1], nothing)
411+
r6 = Reaction(d, [y], nothing, [1], nothing)
412+
r7 = Reaction(d, [x2y], nothing, [1], nothing)
413+
obs_eqs = [X ~ x + 2x2y, Y ~ y + x2y]
414+
rn_prog = ReactionSystem([r1, r2, r3, r4, r5, r6, r7], t, [x, y, x2y], [k, kB, kD, d]; observed = obs_eqs, name=:rn_observed)
415+
416+
# Make simulations.
417+
u0 = [x => 1.0, y => 0.5, x2y => 0.0]
418+
tspan = (0.0, 15.0)
419+
ps = [k => 1.0, kD => 0.1, kB => 0.5, d => 5.0]
420+
oprob_dsl = ODEProblem(rn_dsl, u0, tspan, ps)
421+
oprob_prog = ODEProblem(rn_prog, u0, tspan, ps)
422+
423+
sol_dsl = solve(oprob_dsl, Tsit5(); saveat=0.1)
424+
sol_prog = solve(oprob_prog, Tsit5(); saveat=0.1)
425+
426+
# Tests observables equal in both cases.
427+
@test oprob_dsl[:X] == oprob_prog[:X]
428+
@test oprob_dsl[:Y] == oprob_prog[:Y]
429+
@test sol_dsl[:X] == sol_prog[:X]
430+
@test sol_dsl[:Y] == sol_prog[:Y]
431+
end
432+
390433
# Tests for complicated observable formula.
391434
# Tests using a single observable (without begin/end statement).
392435
# Tests using observable component not part of reaction.
@@ -410,14 +453,39 @@ let
410453
@test sol[:X][1] == u0[:X1]^2 + ps[:op_1]*(u0[:X2] + 2*u0[:X3]) + u0[:X1]*u0[:X4]/ps[:op_2] + ps[:p]
411454
end
412455

456+
# Declares observables implicitly/explicitly.
457+
let
458+
# Basic case.
459+
rn1 = @reaction_network rn_observed begin
460+
@observables X ~ X1 + X2
461+
k, 0 --> X1 + X2
462+
end
463+
rn2 = @reaction_network rn_observed begin
464+
@variables X(t)
465+
@observables X ~ X1 + X2
466+
k, 0 --> X1 + X2
467+
end
468+
@test isequal(rn1, rn2)
469+
470+
# Case with metadata.
471+
rn3 = @reaction_network rn_observed begin
472+
@observables (X, [bounds=(0.0, 10.0)]) ~ X1 + X2
473+
k, 0 --> X1 + X2
474+
end
475+
rn4 = @reaction_network rn_observed begin
476+
@variables X(t) [bounds=(0.0, 10.0)]
477+
@observables X ~ X1 + X2
478+
k, 0 --> X1 + X2
479+
end
480+
@test isequal(rn3, rn4)
481+
end
482+
413483
# Tests various erroneous declarations throw errors.
414484
let
415-
# System with undeclared component as observable.
416-
@test_throws Exception @eval @reaction_network begin
417-
@observables begin
418-
X ~ X1 + X2
419-
end
420-
(p,d), 0 <--> X1
485+
# Independent variable in @compounds.
486+
@test_throws Exception @eval @reaction_network rn_observed begin
487+
@observables X(t) ~ X1 + X2
488+
k, 0 --> X1 + X2
421489
end
422490

423491
# System with observable in observable formula.
@@ -429,7 +497,13 @@ let
429497
(p,d), 0 <--> X1 + X2
430498
end
431499

432-
# System with multiple observables blocks.
500+
# Multiple @compounds options
501+
@test_throws Exception @eval @reaction_network rn_observed begin
502+
@observables X ~ X1 + X2
503+
@observables Y ~ Y1 + Y2
504+
k, 0 --> X1 + X2
505+
k, 0 --> Y1 + Y2
506+
end
433507
@test_throws Exception @eval @reaction_network begin
434508
@observables begin
435509
X ~ X1 + X2
@@ -440,19 +514,31 @@ let
440514
(p,d), 0 <--> X1 + X2
441515
end
442516

443-
# System with no trivial observable left-hand side.
444-
@test_throws Exception @eval @reaction_network begin
445-
@observables begin
446-
X + X2 ~ 2X1
447-
end
448-
(p,d), 0 <--> X1 + X2
517+
# Default value for compound.
518+
@test_throws Exception @eval @reaction_network rn_observed begin
519+
@observables (X = 1.0) ~ X1 + X2
520+
k, 0 --> X1 + X2
449521
end
450522

451-
# A forbidden symbol used as observable name.
452-
@test_throws Exception @eval @reaction_network begin
453-
@observables begin
454-
t ~ X1 + X2
455-
end
456-
(p,d), 0 <--> X1 + X2
523+
# Forbidden symbols as observable names.
524+
@test_throws Exception @eval @reaction_network rn_observed begin
525+
@observables t ~ t1 + t2
526+
k, 0 --> t1 + t2
527+
end
528+
@test_throws Exception @eval @reaction_network rn_observed begin
529+
@observables im ~ i + m
530+
k, 0 --> i + m
531+
end
532+
533+
# Non-trivial observables expression.
534+
@test_throws Exception @eval @reaction_network rn_observed begin
535+
@observables X - X1 ~ X2
536+
k, 0 --> X1 + X2
537+
end
538+
539+
# Occurrence of undeclared dependants.
540+
@test_throws Exception @eval @reaction_network rn_observed begin
541+
@observables X ~ X1 + X2
542+
k, 0 --> X1
457543
end
458544
end

0 commit comments

Comments
 (0)