Skip to content

Commit 8a604c4

Browse files
authored
Merge pull request #823 from isaacsas/drop_mutation
Drop mutating API functions and macro
2 parents 2276e1c + 0b75921 commit 8a604c4

File tree

10 files changed

+100
-530
lines changed

10 files changed

+100
-530
lines changed

HISTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Catalyst unreleased (master branch)
44

55
## Catalyst 14.0
6+
- To be more consistent with ModelingToolkit's immutability requirement for systems, we have removed API functions that mutate `ReactionSystem`s such as `addparam!`, `addreaction!`, `addspecies`, `@add_reactions`, and `merge!`. Please use `ModelingToolkit.extend` and `ModelingToolkit.compose` to generate new merged and/or composed `ReactionSystem`s from multiple component systems.
67
- Added CatalystStructuralIdentifiabilityExtension, which permits StructuralIdentifiability.jl function to be applied directly to Catalyst systems. E.g. use
78
```julia
89
using Catalyst, StructuralIdentifiability

docs/src/api/catalyst_api.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,21 +181,14 @@ reactionrates
181181
```
182182

183183
## [Functions to extend or modify a network](@id api_network_extension_and_modification)
184-
`ReactionSystem`s can be programmatically extended using
185-
[`@add_reactions`](@ref), [`addspecies!`](@ref), [`addparam!`](@ref) and
186-
[`addreaction!`](@ref), or using [`ModelingToolkit.extend`](@ref) and
184+
`ReactionSystem`s can be programmatically extended using [`ModelingToolkit.extend`](@ref) and
187185
[`ModelingToolkit.compose`](@ref).
188186

189187
```@docs
190-
@add_reactions
191-
addspecies!
192-
addparam!
193-
addreaction!
194188
setdefaults!
195189
ModelingToolkit.extend
196190
ModelingToolkit.compose
197191
Catalyst.flatten
198-
merge!(network1::ReactionSystem, network2::ReactionSystem)
199192
```
200193

201194
## Network analysis and representations
@@ -282,7 +275,7 @@ ModelingToolkit.structural_simplify
282275
```
283276

284277
## Chemistry-related functionalities
285-
Various functionalities primarily relevant to modelling of chemical systems (but potentially also in biology).
278+
Various functionalities primarily relevant to modelling of chemical systems (but potentially also in biology).
286279
```@docs
287280
@compound
288281
@compounds

docs/src/catalyst_functionality/network_analysis.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,7 @@ given function is used.
493493
Because of the caching of network properties, subsequent calls to most API
494494
functions will be fast, simply returning the previously calculated and cached
495495
values. In some cases it may be desirable to reset the cache and recalculate
496-
these properties, for example after modifying a network (see
497-
[`addspecies!`](@ref), [`addparam!`](@ref), or [`addreaction!`](@ref)). This can
498-
be done by calling
496+
these properties. This can be done by calling
499497
```julia
500498
Catalyst.reset_networkproperties!(rn)
501499
```

src/Catalyst.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export ODEProblem,
8181
const ExprValues = Union{Expr, Symbol, Float64, Int, Bool}
8282
include("expression_utils.jl")
8383
include("reaction_network.jl")
84-
export @reaction_network, @network_component, @add_reactions, @reaction, @species
84+
export @reaction_network, @network_component, @reaction, @species
8585

8686
# registers CRN specific functions using Symbolics.jl
8787
include("registered_functions.jl")
@@ -91,7 +91,7 @@ export mm, mmr, hill, hillr, hillar
9191
include("networkapi.jl")
9292
export species, nonspecies, reactionparams, reactions, speciesmap, paramsmap
9393
export numspecies, numreactions, numreactionparams, setdefaults!, symmap_to_varmap
94-
export make_empty_network, addspecies!, addparam!, addreaction!, reactionparamsmap
94+
export make_empty_network, reactionparamsmap
9595
export dependants, dependents, substoichmat, prodstoichmat, netstoichmat
9696
export conservationlaws, conservedquantities, conservedequations, conservationlaw_constants
9797
export isequivalent

src/networkapi.jl

Lines changed: 3 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,12 +1358,6 @@ function isequivalent(rn1::ReactionSystem, rn2::ReactionSystem; ignorenames = tr
13581358
true
13591359
end
13601360

1361-
function isequal_ignore_names(rn1, rn2)
1362-
Base.depwarn("Catalyst.isequal_ignore_names has been deprecated. Use isequivalent(rn1, rn2) instead.",
1363-
:isequal_ignore_names; force = true)
1364-
isequivalent(rn1, rn2)
1365-
end
1366-
13671361
"""
13681362
==(rn1::ReactionSystem, rn2::ReactionSystem)
13691363
@@ -1392,159 +1386,6 @@ function make_empty_network(; iv = DEFAULT_IV, name = gensym(:ReactionSystem))
13921386
ReactionSystem(Reaction[], iv, [], []; name = name)
13931387
end
13941388

1395-
"""
1396-
addspecies!(network::ReactionSystem, s::Symbolic; disablechecks=false)
1397-
1398-
Given a [`ReactionSystem`](@ref), add the species corresponding to the variable
1399-
`s` to the network (if it is not already defined). Returns the integer id of the
1400-
species within the system.
1401-
1402-
Notes:
1403-
- `disablechecks` will disable checking for whether the passed in variable is
1404-
already defined, which is useful when adding many new variables to the system.
1405-
*Do not disable checks* unless you are sure the passed in variable is a new
1406-
variable, as this will potentially leave the system in an undefined state.
1407-
"""
1408-
function addspecies!(network::ReactionSystem, s::Symbolic; disablechecks = false)
1409-
reset_networkproperties!(network)
1410-
1411-
isconstant(s) && error("Constant species should be added via addparams!.")
1412-
isspecies(s) ||
1413-
error("$s is not a valid symbolic species. Please use @species to declare it.")
1414-
1415-
# we don't check subsystems since we will add it to the top-level system...
1416-
curidx = disablechecks ? nothing : findfirst(S -> isequal(S, s), get_unknowns(network))
1417-
if curidx === nothing
1418-
push!(get_unknowns(network), s)
1419-
sort!(get_unknowns(network); by = !isspecies)
1420-
push!(get_species(network), s)
1421-
MT.process_variables!(get_var_to_name(network), get_defaults(network), [s])
1422-
return length(get_species(network))
1423-
else
1424-
return curidx
1425-
end
1426-
end
1427-
1428-
"""
1429-
addspecies!(network::ReactionSystem, s::Num; disablechecks=false)
1430-
1431-
Given a [`ReactionSystem`](@ref), add the species corresponding to the
1432-
variable `s` to the network (if it is not already defined). Returns the
1433-
integer id of the species within the system.
1434-
1435-
- `disablechecks` will disable checking for whether the passed in variable is
1436-
already defined, which is useful when adding many new variables to the system.
1437-
*Do not disable checks* unless you are sure the passed in variable is a new
1438-
variable, as this will potentially leave the system in an undefined state.
1439-
"""
1440-
function addspecies!(network::ReactionSystem, s::Num; disablechecks = false)
1441-
addspecies!(network, value(s), disablechecks = disablechecks)
1442-
end
1443-
1444-
"""
1445-
addparam!(network::ReactionSystem, p::Symbolic; disablechecks=false)
1446-
1447-
Given a [`ReactionSystem`](@ref), add the parameter corresponding to the
1448-
variable `p` to the network (if it is not already defined). Returns the integer
1449-
id of the parameter within the system.
1450-
1451-
- `disablechecks` will disable checking for whether the passed in variable is
1452-
already defined, which is useful when adding many new variables to the system.
1453-
*Do not disable checks* unless you are sure the passed in variable is a new
1454-
variable, as this will potentially leave the system in an undefined state.
1455-
"""
1456-
function addparam!(network::ReactionSystem, p::Symbolic; disablechecks = false)
1457-
reset_networkproperties!(network)
1458-
1459-
# we don't check subsystems since we will add it to the top-level system...
1460-
if istree(p) && !(operation(p) isa Symbolic && !istree(operation(p)))
1461-
error("If the passed in parameter is an expression, it must correspond to an underlying Variable.")
1462-
end
1463-
curidx = disablechecks ? nothing : findfirst(S -> isequal(S, p), get_ps(network))
1464-
if curidx === nothing
1465-
push!(get_ps(network), p)
1466-
MT.process_variables!(get_var_to_name(network), get_defaults(network), [p])
1467-
return length(get_ps(network))
1468-
else
1469-
return curidx
1470-
end
1471-
end
1472-
1473-
"""
1474-
addparam!(network::ReactionSystem, p::Num; disablechecks=false)
1475-
1476-
Given a [`ReactionSystem`](@ref), add the parameter corresponding to the
1477-
variable `p` to the network (if it is not already defined). Returns the
1478-
integer id of the parameter within the system.
1479-
1480-
- `disablechecks` will disable checking for whether the passed in variable is
1481-
already defined, which is useful when adding many new variables to the system.
1482-
*Do not disable checks* unless you are sure the passed in variable is a new
1483-
variable, as this will potentially leave the system in an undefined state.
1484-
"""
1485-
function addparam!(network::ReactionSystem, p::Num; disablechecks = false)
1486-
addparam!(network, value(p); disablechecks = disablechecks)
1487-
end
1488-
1489-
"""
1490-
addreaction!(network::ReactionSystem, rx::Reaction)
1491-
1492-
Add the passed in reaction to the [`ReactionSystem`](@ref). Returns the
1493-
integer id of `rx` in the list of `Reaction`s within `network`.
1494-
1495-
Notes:
1496-
- Any new species or parameters used in `rx` should be separately added to
1497-
`network` using [`addspecies!`](@ref) and [`addparam!`](@ref).
1498-
"""
1499-
function addreaction!(network::ReactionSystem, rx::Reaction)
1500-
reset_networkproperties!(network)
1501-
push!(get_eqs(network), rx)
1502-
sort(get_eqs(network); by = eqsortby)
1503-
push!(get_rxs(network), rx)
1504-
length(get_rxs(network))
1505-
end
1506-
1507-
"""
1508-
merge!(network1::ReactionSystem, network2::ReactionSystem)
1509-
1510-
Merge `network2` into `network1`.
1511-
1512-
Notes:
1513-
- Duplicate reactions between the two networks are not filtered out.
1514-
- [`Reaction`](@ref)s are not deepcopied to minimize allocations, so both
1515-
networks will share underlying data arrays.
1516-
- Subsystems are not deepcopied between the two networks and will hence be
1517-
shared.
1518-
- Returns `network1`.
1519-
- `combinatoric_ratelaws` is the value of `network1`.
1520-
"""
1521-
function Base.merge!(network1::ReactionSystem, network2::ReactionSystem)
1522-
isequal(get_iv(network1), get_iv(network2)) ||
1523-
error("Reaction networks must have the same independent variable to be mergable.")
1524-
union!(get_sivs(network1), get_sivs(network2))
1525-
1526-
union!(get_eqs(network1), get_eqs(network2))
1527-
sort!(get_eqs(network1), by = eqsortby)
1528-
union!(get_rxs(network1), get_rxs(network2))
1529-
(count(eq -> eq isa Reaction, get_eqs(network1)) == length(get_rxs(network1))) ||
1530-
error("Unequal number of reactions from get_rxs(sys) and get_eqs(sys) after merging.")
1531-
1532-
union!(get_unknowns(network1), get_unknowns(network2))
1533-
sort!(get_unknowns(network1), by = !isspecies)
1534-
union!(get_species(network1), get_species(network2))
1535-
(count(isspecies, get_unknowns(network1)) == length(get_species(network1))) ||
1536-
error("Unequal number of species from get_species(sys) and get_unknowns(sys) after merging.")
1537-
1538-
union!(get_ps(network1), get_ps(network2))
1539-
union!(get_observed(network1), get_observed(network2))
1540-
union!(get_systems(network1), get_systems(network2))
1541-
merge!(get_defaults(network1), get_defaults(network2))
1542-
union!(MT.get_continuous_events(network1), MT.get_continuous_events(network2))
1543-
union!(MT.get_discrete_events(network1), MT.get_discrete_events(network2))
1544-
1545-
reset_networkproperties!(network1)
1546-
network1
1547-
end
15481389

15491390
############################### units #####################################
15501391

@@ -1616,7 +1457,7 @@ function validate(rs::ReactionSystem, info::String = "")
16161457
if (specunits in (MT.unitless, nothing)) && (timeunits in (MT.unitless, nothing))
16171458
all(u == 1.0 for u in ModelingToolkit.get_unit(get_ps(rs))) && return true
16181459
end
1619-
1460+
16201461
rateunits = specunits / timeunits
16211462
for rx in get_rxs(rs)
16221463
rxunits = get_unit(rx.rate)
@@ -1628,12 +1469,12 @@ function validate(rs::ReactionSystem, info::String = "")
16281469
# Needs additional checks because for cases: (1.0^n) and (1.0^n1)*(1.0^n2).
16291470
# These are not considered (be default) considered equal to `1.0` for unitless reactions.
16301471
isequal(rxunits, rateunits) && continue
1631-
if istree(rxunits)
1472+
if istree(rxunits)
16321473
unitless_exp(rxunits) && continue
16331474
(operation(rxunits) == *) && all(unitless_exp(arg) for arg in arguments(rxunits)) && continue
16341475
end
16351476
validated = false
1636-
@warn(string("Reaction rate laws are expected to have units of ", rateunits, " however, ",
1477+
@warn(string("Reaction rate laws are expected to have units of ", rateunits, " however, ",
16371478
rx, " has units of ", rxunits, "."))
16381479
end
16391480

0 commit comments

Comments
 (0)