@@ -360,14 +360,16 @@ function make_reaction_system(ex::Expr; name = :(gensym(:ReactionSystem)))
360
360
361
361
# Reads options.
362
362
compound_expr, compound_species = read_compound_options (options)
363
- observed_vars, observed_eqs = read_observed_options (options)
364
363
365
364
# Parses reactions, species, and parameters.
366
365
reactions = get_reactions (reaction_lines)
367
366
species_declared = [extract_syms (options, :species ); compound_species]
368
367
parameters_declared = extract_syms (options, :parameters )
369
368
variables = extract_syms (options, :variables )
370
369
370
+ # Reads more options.
371
+ observed_vars, observed_eqs = read_observed_options (options, [species_declared; variables])
372
+
371
373
# handle independent variables
372
374
if haskey (options, :ivs )
373
375
ivs = Tuple (extract_syms (options, :ivs ))
@@ -688,19 +690,31 @@ end
688
690
# Most options handled in previous sections, when code re-organised, these should ideally be moved to the same place.
689
691
690
692
# Reads the observables options. Outputs an expression ofr creating the obervable variables, and a vector of observable equations.
691
- function read_observed_options (options)
693
+ function read_observed_options (options, species_declared )
692
694
if haskey (options, :observables )
693
695
# Gets list of observable equations and prepares variable declaration expression.
694
696
# (`options[:observables]` inlucdes `@observables`, `.args[3]` removes this part)
695
697
observed_eqs = make_observed_eqs (options[:observables ]. args[3 ])
696
- observed_vars = : (@variables )
698
+ observed_vars = Expr ( :block , : (@variables ) )
697
699
698
- # For each observable, checks for errors and adds the variable to `observed_vars`.
699
700
for obs_eq in observed_eqs. args
700
- (obs_eq. args[1 ] != :~ ) && error (" Malformed observable formula :\" $(obs_eq) \" . Formula should contain two expressions separated by a '~'." )
701
- (obs_eq. args[2 ] isa Symbol) || error (" Malformed observable formula :\" $(obs_eq) \" . Left hand side should be a single symbol." )
702
- in (obs_eq. args[2 ], forbidden_symbols_error) && error (" A forbidden symbol ($(obs_eq. args[2 ]) ) was used as an observable name." )
703
- push! (observed_vars. args, obs_eq. args[2 ])
701
+ # Extract the observable, checks errors, and continues the loop if the observable has been declared.
702
+ obs_name, ivs, defaults, _ = find_varinfo_in_declaration (obs_eq. args[2 ])
703
+ isempty (ivs) || error (" An observable ($obs_name ) was given independent variable(s). These should not be given, as they are inferred automatically." )
704
+ isnothing (defaults) || error (" An observable ($obs_name ) was given a default value. This is forbidden." )
705
+ in (obs_name, forbidden_symbols_error) && error (" A forbidden symbol ($(obs_eq. args[2 ]) ) was used as an observable name." )
706
+ (obs_name in species_declared) && continue
707
+
708
+ # Appends (..) to the observable (which is later replaced with the extracted ivs).
709
+ # Adds the observable to the first line of the output expression (starting with `@variables`).
710
+ obs_expr = insert_independent_variable (obs_eq. args[2 ], :(.. ))
711
+ push! (observed_vars. args[1 ]. args, obs_expr)
712
+
713
+ # Adds a line to the `observed_vars` expression, setting the ivs for this observable.
714
+ dependants = [rs. reactant for rs in
715
+ Catalyst. recursive_find_reactants! (obs_eq. args[3 ], 1 , Vector {ReactantStruct} (undef, 0 ))]
716
+ ivs_get_expr = :(unique (reduce (vcat,[arguments (ModelingToolkit. unwrap (dep)) for dep in $ dependants])))
717
+ push! (observed_vars. args, :($ obs_name = $ (obs_name)($ (ivs_get_expr). .. )))
704
718
end
705
719
else
706
720
# If option is not used, return empty expression and vector.
0 commit comments