1
- # ## Species Structure ###
1
+ # ## Species Symbolic Variable Definition ###
2
2
3
- # Catalyst specific symbolics to support SBML
3
+ # Defines species-related metadata.
4
4
struct ParameterConstantSpecies end
5
5
struct VariableBCSpecies end
6
6
struct VariableSpecies end
7
7
Symbolics. option_to_metadata_type (:: Val{:isconstantspecies} ) = ParameterConstantSpecies
8
8
Symbolics. option_to_metadata_type (:: Val{:isbcspecies} ) = VariableBCSpecies
9
9
Symbolics. option_to_metadata_type (:: Val{:isspecies} ) = VariableSpecies
10
10
11
+ # Defines species-related metadata getters.
11
12
"""
12
13
Catalyst.isconstant(s)
13
14
@@ -52,14 +53,13 @@ function tospecies(s)
52
53
MT. setmetadata (s, VariableSpecies, true )
53
54
end
54
55
55
- # true for species which shouldn't change from the reactions, including non-species
56
- # variables
56
+ # Function returning ` true`` for species which shouldn't change from the reactions,
57
+ # including non-species variables.
57
58
drop_dynamics (s) = isconstant (s) || isbc (s) || (! isspecies (s))
58
59
59
60
60
61
# ## Reaction Structure ###
61
62
62
-
63
63
"""
64
64
$(TYPEDEF)
65
65
@@ -129,13 +129,7 @@ struct Reaction{S, T}
129
129
metadata:: Vector{Pair{Symbol, Any}}
130
130
end
131
131
132
- """
133
- isvalidreactant(s)
134
-
135
- Test if a species is valid as a reactant (i.e. a species variable or a constant parameter).
136
- """
137
- isvalidreactant (s) = MT. isparameter (s) ? isconstant (s) : (isspecies (s) && ! isconstant (s))
138
-
132
+ # Five-argument constructor accepting rate, substrates, and products, and their stoichiometries.
139
133
function Reaction (rate, subs, prods, substoich, prodstoich;
140
134
netstoich = nothing , metadata = Pair{Symbol, Any}[],
141
135
only_use_rate = metadata_only_use_rate_check (metadata), kwargs... )
@@ -208,18 +202,53 @@ function Reaction(rate, subs, prods, substoich, prodstoich;
208
202
Reaction (value (rate), subs, prods, substoich′, prodstoich′, ns, only_use_rate, metadata)
209
203
end
210
204
205
+ # Three argument constructor assumes stoichiometric coefs are one and integers.
206
+ function Reaction (rate, subs, prods; kwargs... )
207
+ sstoich = isnothing (subs) ? nothing : ones (Int, length (subs))
208
+ pstoich = isnothing (prods) ? nothing : ones (Int, length (prods))
209
+ Reaction (rate, subs, prods, sstoich, pstoich; kwargs... )
210
+ end
211
+
212
+ """
213
+ isvalidreactant(s)
214
+
215
+ Test if a species is valid as a reactant (i.e. a species variable or a constant parameter).
216
+ """
217
+ isvalidreactant (s) = MT. isparameter (s) ? isconstant (s) : (isspecies (s) && ! isconstant (s))
218
+
211
219
# Checks if a metadata input has an entry :only_use_rate => true
212
220
function metadata_only_use_rate_check (metadata)
213
221
only_use_rate_idx = findfirst (:only_use_rate == entry[1 ] for entry in metadata)
214
222
isnothing (only_use_rate_idx) && return false
215
223
return Bool (metadata[only_use_rate_idx][2 ])
216
224
end
217
225
218
- # three argument constructor assumes stoichiometric coefs are one and integers
219
- function Reaction (rate, subs, prods; kwargs... )
220
- sstoich = isnothing (subs) ? nothing : ones (Int, length (subs))
221
- pstoich = isnothing (prods) ? nothing : ones (Int, length (prods))
222
- Reaction (rate, subs, prods, sstoich, pstoich; kwargs... )
226
+ # calculates the net stoichiometry of a reaction as a vector of pairs (sub,substoich)
227
+ function get_netstoich (subs, prods, sstoich, pstoich)
228
+ # stoichiometry as a Dictionary
229
+ nsdict = Dict {Any, eltype(sstoich)} (sub => - sstoich[i] for (i, sub) in enumerate (subs))
230
+ for (i, p) in enumerate (prods)
231
+ coef = pstoich[i]
232
+ @inbounds nsdict[p] = haskey (nsdict, p) ? nsdict[p] + coef : coef
233
+ end
234
+
235
+ # stoichiometry as a vector
236
+ [el for el in nsdict if ! _iszero (el[2 ])]
237
+ end
238
+
239
+ # Get the net stoichiometries' type.
240
+ netstoich_stoichtype (:: Vector{Pair{S, T}} ) where {S, T} = T
241
+
242
+
243
+ # ## Base and MTK Accessors ###
244
+
245
+ # Show function for `Reaction`s.
246
+ function Base. show (io:: IO , rx:: Reaction )
247
+ print (io, rx. rate, " , " )
248
+ print_rxside (io, rx. substrates, rx. substoich)
249
+ arrow = rx. only_use_rate ? " ⇒" : " -->"
250
+ print (io, " " , arrow, " " )
251
+ print_rxside (io, rx. products, rx. prodstoich)
223
252
end
224
253
225
254
function print_rxside (io:: IO , specs, stoich)
@@ -244,21 +273,6 @@ function print_rxside(io::IO, specs, stoich)
244
273
nothing
245
274
end
246
275
247
- function Base. show (io:: IO , rx:: Reaction )
248
- print (io, rx. rate, " , " )
249
- print_rxside (io, rx. substrates, rx. substoich)
250
- arrow = rx. only_use_rate ? " ⇒" : " -->"
251
- print (io, " " , arrow, " " )
252
- print_rxside (io, rx. products, rx. prodstoich)
253
- end
254
-
255
- function apply_if_nonempty (f, v)
256
- isempty (v) && return v
257
- s = similar (v)
258
- map! (f, s, v)
259
- s
260
- end
261
-
262
276
function ModelingToolkit. namespace_equation (rx:: Reaction , name; kw... )
263
277
f = Base. Fix2 (namespace_expr, name)
264
278
rate = f (rx. rate)
@@ -275,20 +289,19 @@ function ModelingToolkit.namespace_equation(rx::Reaction, name; kw...)
275
289
Reaction (rate, subs, prods, substoich, prodstoich, netstoich, rx. only_use_rate, rx. metadata)
276
290
end
277
291
278
- netstoich_stoichtype (:: Vector{Pair{S, T}} ) where {S, T} = T
292
+ function apply_if_nonempty (f, v)
293
+ isempty (v) && return v
294
+ s = similar (v)
295
+ map! (f, s, v)
296
+ s
297
+ end
279
298
280
- # calculates the net stoichiometry of a reaction as a vector of pairs (sub,substoich)
281
- function get_netstoich (subs, prods, sstoich, pstoich)
282
- # stoichiometry as a Dictionary
283
- nsdict = Dict {Any, eltype(sstoich)} (sub => - sstoich[i] for (i, sub) in enumerate (subs))
284
- for (i, p) in enumerate (prods)
285
- coef = pstoich[i]
286
- @inbounds nsdict[p] = haskey (nsdict, p) ? nsdict[p] + coef : coef
287
- end
299
+ # Overwrites functions in ModelingToolkit to give the correct input.
300
+ ModelingToolkit. is_diff_equation (rx:: Reaction ) = false
301
+ ModelingToolkit. is_alg_equation (rx:: Reaction ) = false
288
302
289
- # stoichiometry as a vector
290
- [el for el in nsdict if ! _iszero (el[2 ])]
291
- end
303
+
304
+ # ## Reaction-specific Accessors ###
292
305
293
306
"""
294
307
isbcbalanced(rx::Reaction)
@@ -315,8 +328,107 @@ function isbcbalanced(rx::Reaction)
315
328
true
316
329
end
317
330
318
- # ## Reaction Acessor Functions ###
331
+ # ## Reaction Metadata Implementation ###
332
+ # These are currently considered internal, but can be used by public accessor functions like get_noise_scaling.
319
333
320
- # Overwrites functions in ModelingToolkit to give the correct input.
321
- ModelingToolkit. is_diff_equation (rx:: Reaction ) = false
322
- ModelingToolkit. is_alg_equation (rx:: Reaction ) = false
334
+ """
335
+ getmetadata_dict(reaction::Reaction)
336
+
337
+ Retrives the `ImmutableDict` containing all of the metadata associated with a specific reaction.
338
+
339
+ Arguments:
340
+ - `reaction`: The reaction for which we wish to retrive all metadata.
341
+
342
+ Example:
343
+ ```julia
344
+ reaction = @reaction k, 0 --> X, [description="Production reaction"]
345
+ getmetadata_dict(reaction)
346
+ ```
347
+ """
348
+ function getmetadata_dict (reaction:: Reaction )
349
+ return reaction. metadata
350
+ end
351
+
352
+ """
353
+ hasmetadata(reaction::Reaction, md_key::Symbol)
354
+
355
+ Checks if a `Reaction` have a certain metadata field. If it does, returns `true` (else returns `false`).
356
+
357
+ Arguments:
358
+ - `reaction`: The reaction for which we wish to check if a specific metadata field exist.
359
+ - `md_key`: The metadata for which we wish to check existence of.
360
+
361
+ Example:
362
+ ```julia
363
+ reaction = @reaction k, 0 --> X, [description="Production reaction"]
364
+ hasmetadata(reaction, :description)
365
+ ```
366
+ """
367
+ function hasmetadata (reaction:: Reaction , md_key:: Symbol )
368
+ return any (isequal (md_key, entry[1 ]) for entry in getmetadata_dict (reaction))
369
+ end
370
+
371
+ """
372
+ getmetadata(reaction::Reaction, md_key::Symbol)
373
+
374
+ Retrives a certain metadata value from a `Reaction`. If the metadata does not exists, throws an error.
375
+
376
+ Arguments:
377
+ - `reaction`: The reaction for which we wish to retrive a specific metadata value.
378
+ - `md_key`: The metadata for which we wish to retrive.
379
+
380
+ Example:
381
+ ```julia
382
+ reaction = @reaction k, 0 --> X, [description="Production reaction"]
383
+ getmetadata(reaction, :description)
384
+ ```
385
+ """
386
+ function getmetadata (reaction:: Reaction , md_key:: Symbol )
387
+ if ! hasmetadata (reaction, md_key)
388
+ error (" The reaction does not have a metadata field $md_key . It does have the following metadata fields: $(keys (getmetadata_dict (reaction))) ." )
389
+ end
390
+ metadata = getmetadata_dict (reaction)
391
+ return metadata[findfirst (isequal (md_key, entry[1 ]) for entry in getmetadata_dict (reaction))][2 ]
392
+ end
393
+
394
+ # ## Implemented Reaction Metadata ###
395
+
396
+ # Noise scaling.
397
+ """
398
+ has_noise_scaling(reaction::Reaction)
399
+
400
+ Checks whether a specific reaction has the metadata field `noise_scaing`. If so, returns `true`, else
401
+ returns `false`.
402
+
403
+ Arguments:
404
+ - `reaction`: The reaction for which we wish to check.
405
+
406
+ Example:
407
+ ```julia
408
+ reaction = @reaction k, 0 --> X, [noise_scaling=0.0]
409
+ has_noise_scaling(reaction)
410
+ """
411
+ function has_noise_scaling (reaction:: Reaction )
412
+ return hasmetadata (reaction, :noise_scaling )
413
+ end
414
+
415
+ """
416
+ get_noise_scaling(reaction::Reaction)
417
+
418
+ Returns the noise_scaling metadata from a specific reaction.
419
+
420
+ Arguments:
421
+ - `reaction`: The reaction for which we wish to retrive all metadata.
422
+
423
+ Example:
424
+ ```julia
425
+ reaction = @reaction k, 0 --> X, [noise_scaling=0.0]
426
+ get_noise_scaling(reaction)
427
+ """
428
+ function get_noise_scaling (reaction:: Reaction )
429
+ if has_noise_scaling (reaction)
430
+ return getmetadata (reaction, :noise_scaling )
431
+ else
432
+ error (" Attempts to access noise_scaling metadata field for a reaction which does not have a value assigned for this metadata." )
433
+ end
434
+ end
0 commit comments