@@ -124,7 +124,7 @@ macro reaction_network(name::Symbol = gensym(:ReactionSystem))
124
124
end
125
125
126
126
# Handles two disjoint cases.
127
- macro reaction_network (expr:: Expr )
127
+ macro reaction_network (expr:: Expr )
128
128
# Case 1: The input is a name with interpolation.
129
129
(expr. head != :block ) && return make_rs_expr (esc (expr. args[1 ]))
130
130
# Case 2: The input is a reaction network (and no name is provided).
@@ -156,7 +156,7 @@ macro network_component(name::Symbol = gensym(:ReactionSystem))
156
156
end
157
157
158
158
# Handles two disjoint cases.
159
- macro network_component (expr:: Expr )
159
+ macro network_component (expr:: Expr )
160
160
# Case 1: The input is a name with interpolation.
161
161
(expr. head != :block ) && return make_rs_expr (esc (expr. args[1 ]); complete = false )
162
162
# Case 2: The input is a reaction network (and no name is provided).
@@ -180,7 +180,6 @@ function make_rs_expr(name, network_expr; complete = true)
180
180
return rs_expr
181
181
end
182
182
183
-
184
183
# ## Internal DSL Structures ###
185
184
186
185
# Internal structure containing information about one reactant in one reaction.
@@ -197,8 +196,8 @@ struct ReactionInternal
197
196
rate:: ExprValues
198
197
metadata:: Expr
199
198
200
- function ReactionInternal (sub_line:: ExprValues , prod_line:: ExprValues , rate :: ExprValues ,
201
- metadata_line:: ExprValues )
199
+ function ReactionInternal (sub_line:: ExprValues , prod_line:: ExprValues ,
200
+ rate :: ExprValues , metadata_line:: ExprValues )
202
201
subs = recursive_find_reactants! (sub_line, 1 , Vector {ReactantInternal} (undef, 0 ))
203
202
prods = recursive_find_reactants! (prod_line, 1 , Vector {ReactantInternal} (undef, 0 ))
204
203
metadata = extract_metadata (metadata_line)
211
210
# reactants are stored in the `reactants` vector. As the expression tree is parsed, the
212
211
# stoichiometry is updated and new reactants added.
213
212
function recursive_find_reactants! (ex:: ExprValues , mult:: ExprValues ,
214
- reactants:: Vector{ReactantInternal} )
213
+ reactants:: Vector{ReactantInternal} )
215
214
# We have reached the end of the expression tree and can finalise and return the reactants.
216
215
if typeof (ex) != Expr || (ex. head == :escape ) || (ex. head == :ref )
217
216
# The final bit of the expression is not a relevant reactant, no additions are required.
@@ -223,23 +222,23 @@ function recursive_find_reactants!(ex::ExprValues, mult::ExprValues,
223
222
new_mult = processmult (+ , mult, reactants[idx]. stoichiometry)
224
223
reactants[idx] = ReactantInternal (ex, new_mult)
225
224
226
- # If the expression corresponds to a new reactant, add it to the list.
225
+ # If the expression corresponds to a new reactant, add it to the list.
227
226
else
228
227
push! (reactants, ReactantInternal (ex, mult))
229
228
end
230
229
231
- # If we have encountered a multiplication (i.e. a stoichiometry and a set of reactants).
230
+ # If we have encountered a multiplication (i.e. a stoichiometry and a set of reactants).
232
231
elseif ex. args[1 ] == :*
233
232
# The normal case (e.g. 3*X or 3*(X+Y)). Update the current multiplicity and continue.
234
233
if length (ex. args) == 3
235
234
new_mult = processmult (* , mult, ex. args[2 ])
236
235
recursive_find_reactants! (ex. args[3 ], new_mult, reactants)
237
- # More complicated cases (e.g. 2*3*X). Yes, `ex.args[1:(end - 1)]` should start at 1 (not 2).
236
+ # More complicated cases (e.g. 2*3*X). Yes, `ex.args[1:(end - 1)]` should start at 1 (not 2).
238
237
else
239
238
new_mult = processmult (* , mult, Expr (:call , ex. args[1 : (end - 1 )]. .. ))
240
239
recursive_find_reactants! (ex. args[end ], new_mult, reactants)
241
240
end
242
- # If we have encountered a sum of different reactants, apply recursion on each.
241
+ # If we have encountered a sum of different reactants, apply recursion on each.
243
242
elseif ex. args[1 ] == :+
244
243
for i in 2 : length (ex. args)
245
244
recursive_find_reactants! (ex. args[i], mult, reactants)
@@ -289,35 +288,38 @@ function make_reaction_system(ex::Expr, name)
289
288
290
289
# Extracts the options used (throwing errors for repeated options).
291
290
if ! allunique (arg. args[1 ] for arg in option_lines)
292
- error (" Some options where given multiple times." )
291
+ error (" Some options where given multiple times." )
293
292
end
294
293
options = Dict (Symbol (String (arg. args[1 ])[2 : end ]) => arg for arg in option_lines)
295
-
294
+
296
295
# Reads options (round 1, options which must be read before the reactions, e.g. because
297
296
# they might declare parameters/species/variables).
298
297
compound_expr_init, compound_species = read_compound_options (options)
299
298
species_declared = [extract_syms (options, :species ); compound_species]
300
299
parameters_declared = extract_syms (options, :parameters )
301
300
variables_declared = extract_syms (options, :variables )
302
- vars_extracted, add_default_diff, equations = read_equations_options (options, variables_declared)
301
+ vars_extracted, add_default_diff, equations = read_equations_options (options,
302
+ variables_declared)
303
303
304
304
# Extracts all reactions. Extracts all parameters, species, and variables of the system and
305
305
# creates lists with them.
306
306
reactions = get_reactions (reaction_lines)
307
307
variables = vcat (variables_declared, vars_extracted)
308
308
syms_declared = Set (Iterators. flatten ((parameters_declared, species_declared,
309
- variables)))
309
+ variables)))
310
310
species_extracted, parameters_extracted = extract_species_and_parameters (reactions,
311
- syms_declared)
311
+ syms_declared)
312
312
species = vcat (species_declared, species_extracted)
313
313
parameters = vcat (parameters_declared, parameters_extracted)
314
314
315
315
# Reads options (round 2, options that either can, or must, be read after the reactions).
316
316
tiv, sivs, ivs, ivexpr = read_ivs_option (options)
317
317
continuous_events_expr = read_events_option (options, :continuous_events )
318
318
discrete_events_expr = read_events_option (options, :discrete_events )
319
- observed_expr, observed_eqs, obs_syms = read_observed_options (options, [species_declared; variables], ivs)
320
- diffexpr = create_differential_expr (options, add_default_diff, [species; parameters; variables], tiv)
319
+ observed_expr, observed_eqs, obs_syms = read_observed_options (options,
320
+ [species_declared; variables], ivs)
321
+ diffexpr = create_differential_expr (options, add_default_diff,
322
+ [species; parameters; variables], tiv)
321
323
default_reaction_metadata = read_default_noise_scaling_option (options)
322
324
combinatoric_ratelaws = read_combinatoric_ratelaws_option (options)
323
325
424
426
425
427
# Takes a reaction line and creates reaction(s) from it and pushes those to the reaction vector.
426
428
# Used to create multiple reactions from bundled reactions (like `k, (X,Y) --> 0`).
427
- function push_reactions! (reactions:: Vector{ReactionInternal} , subs:: ExprValues , prods :: ExprValues ,
428
- rate:: ExprValues , metadata:: ExprValues , arrow:: Symbol )
429
+ function push_reactions! (reactions:: Vector{ReactionInternal} , subs:: ExprValues ,
430
+ prods :: ExprValues , rate:: ExprValues , metadata:: ExprValues , arrow:: Symbol )
429
431
# The rates, substrates, products, and metadata may be in a tuple form (e.g. `k, (X,Y) --> 0`).
430
432
# This finds these tuples' lengths (or 1 for non-tuple forms). Inconsistent lengths yield error.
431
433
lengs = (tup_leng (subs), tup_leng (prods), tup_leng (rate), tup_leng (metadata))
@@ -591,7 +593,6 @@ function get_rxexpr(rx::ReactionInternal)
591
593
return rx_constructor
592
594
end
593
595
594
-
595
596
# ## DSL Option Handling ###
596
597
597
598
# Finds the time idenepdnet variable, and any potential spatial indepndent variables.
621
622
# the `default_noise_scaling` reaction metadata, otherwise, returns an empty vector.
622
623
function read_default_noise_scaling_option (options)
623
624
if haskey (options, :default_noise_scaling )
624
- if (length (options[:default_noise_scaling ]. args) != 3 )
625
+ if (length (options[:default_noise_scaling ]. args) != 3 )
625
626
error (" @default_noise_scaling should only have a single expression as its input, this appears not to be the case: \" $(options[:default_noise_scaling ]) \" " )
626
627
end
627
628
return :([:noise_scaling => $ (options[:default_noise_scaling ]. args[3 ])])
@@ -774,13 +775,13 @@ function read_observed_options(options, species_n_vars_declared, ivs_sorted)
774
775
for (idx, obs_eq) in enumerate (observed_eqs. args)
775
776
# Extract the observable, checks for errors.
776
777
obs_name, ivs, defaults, metadata = find_varinfo_in_declaration (obs_eq. args[2 ])
777
- if ! isempty (ivs)
778
+ if ! isempty (ivs)
778
779
error (" An observable ($obs_name ) was given independent variable(s). These should not be given, as they are inferred automatically." )
779
780
end
780
- if ! isnothing (defaults)
781
+ if ! isnothing (defaults)
781
782
error (" An observable ($obs_name ) was given a default value. This is forbidden." )
782
783
end
783
- if in (obs_name, forbidden_symbols_error)
784
+ if in (obs_name, forbidden_symbols_error)
784
785
error (" A forbidden symbol ($(obs_eq. args[2 ]) ) was used as an observable name." )
785
786
end
786
787
if (obs_name in species_n_vars_declared) && is_escaped_expr (obs_eq. args[2 ])
@@ -803,11 +804,14 @@ function read_observed_options(options, species_n_vars_declared, ivs_sorted)
803
804
# Adds a line to the `observed_expr` expression, setting the ivs for this observable.
804
805
# Cannot extract directly using e.g. "getfield.(dependants_structs, :reactant)" because
805
806
# then we get something like :([:X1, :X2]), rather than :([X1, X2]).
806
- dep_var_expr = :(filter (! MT. isparameter, Symbolics. get_variables ($ (obs_eq. args[3 ]))))
807
- ivs_get_expr = :(unique (reduce (vcat,[arguments (MT. unwrap (dep)) for dep in $ dep_var_expr])))
807
+ dep_var_expr = :(filter (! MT. isparameter,
808
+ Symbolics. get_variables ($ (obs_eq. args[3 ]))))
809
+ ivs_get_expr = :(unique (reduce (vcat,
810
+ [arguments (MT. unwrap (dep)) for dep in $ dep_var_expr])))
808
811
sort_func (iv) = findfirst (MT. getname (iv) == ivs for ivs in ivs_sorted)
809
812
ivs_get_expr_sorted = :(sort ($ (ivs_get_expr); by = sort_func))
810
- push! (observed_expr. args, :($ obs_name = $ (obs_name)($ (ivs_get_expr_sorted). .. )))
813
+ push! (observed_expr. args,
814
+ :($ obs_name = $ (obs_name)($ (ivs_get_expr_sorted). .. )))
811
815
end
812
816
813
817
# In case metadata was given, this must be cleared from `observed_eqs`.
0 commit comments