Skip to content

Commit b2bedf6

Browse files
committed
fixes
1 parent 5bb1d10 commit b2bedf6

File tree

4 files changed

+86
-56
lines changed

4 files changed

+86
-56
lines changed

ext/CatalystGraphMakieExtension.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ module CatalystGraphMakieExtension
22

33
# Fetch packages.
44
using Catalyst, GraphMakie, Graphs
5-
import Catalyst: lattice_plot, lattice_animation, extract_vals
6-
import Graphs: AbstractGraph, SimpleGraph, SimpleDiGraph, SimpleEdge, src, dst, ne, nv
7-
import Catalyst: speciesreactiongraph, incidencematgraph
5+
import Catalyst: lattice_plot, lattice_animation, extract_vals, get_variables!
6+
import Catalyst: species_reaction_graph, incidencematgraph
87

9-
# Creates and exports hc_steady_states function.
8+
# Creates and exports graph plotting functions.
109
include("CatalystGraphMakieExtension/graph_makie_extension_spatial_modelling.jl")
1110
include("CatalystGraphMakieExtension/rn_graph_plot.jl")
12-
export SRGraph, ComplexGraph
1311
end

ext/CatalystGraphMakieExtension/rn_graph_plot.jl

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
88
Wrapper for the species-reaction graph containing edges for rate-dependence on species. Intended to allow plotting of multiple edges.
99
"""
10-
struct SRGraphWrap{T} <: AbstractGraph{T}
10+
struct SRGraphWrap{T} <: Graphs.AbstractGraph{T}
1111
g::SimpleDiGraph{T}
12-
rateedges::Vector{SimpleEdge}
12+
rateedges::Vector{Graphs.SimpleEdge{T}}
13+
edgeorder::Vector{Int64}
1314
end
1415

1516
# Create the SimpleDiGraph corresponding to the species and reactions
1617
function SRGraphWrap(rn::ReactionSystem)
17-
srg = speciesreactiongraph(rn)
18-
rateedges = Vector{SimpleEdge}()
18+
srg = species_reaction_graph(rn)
19+
rateedges = Vector{Graphs.SimpleEdge{Int}}()
1920
sm = speciesmap(rn); specs = species(rn)
2021

2122
deps = Set()
@@ -25,11 +26,13 @@ function SRGraphWrap(rn::ReactionSystem)
2526
if !isempty(deps)
2627
for spec in deps
2728
specidx = sm[spec]
28-
push!(rateedges, SimpleEdge(specidx, i + length(specs)))
29+
push!(rateedges, Graphs.SimpleEdge(specidx, i + length(specs)))
2930
end
3031
end
3132
end
32-
SRGraphWrap(srg, rateedges)
33+
edgelist = vcat(collect(Graphs.edges(srg)), rateedges)
34+
edgeorder = sortperm(edgelist)
35+
SRGraphWrap(srg, rateedges, edgeorder)
3336
end
3437

3538
Base.eltype(g::SRGraphWrap) = eltype(g.g)
@@ -44,8 +47,7 @@ Graphs.vertices(g::SRGraphWrap) = vertices(g.g)
4447
Graphs.is_directed(g::SRGraphWrap) = is_directed(g.g)
4548

4649
function Graphs.edges(g::SRGraphWrap)
47-
edgelist = vcat(collect(Graphs.edges(g.g)), g.rateedges)
48-
edgelist = sort!(edgelist)
50+
edgelist = vcat(collect(Graphs.edges(g.g)), g.rateedges)[g.edgeorder]
4951
end
5052

5153
function gen_distances(g::SRGraphWrap; inc = 0.2)
@@ -60,14 +62,14 @@ end
6062
"""
6163
PetriNet(rn::ReactionSystem)
6264
63-
See the documentation for [`SRGraph`](@ref).
65+
See the documentation for [`plot_network`](@ref).
6466
"""
65-
function PetriNet(rn::ReactionSystem)
66-
SRGraph(rn)
67+
function Catalyst.plot_petrinet(rn::ReactionSystem)
68+
plot_network(rn)
6769
end
6870

6971
"""
70-
SRGraph(rn::ReactionSystem; interactive=false)
72+
plot_network(rn::ReactionSystem; interactive=false)
7173
7274
Converts a [`ReactionSystem`](@ref) into a GraphMakie plot of the species reaction graph.
7375
Reactions correspond to small green circles, and species to blue circles.
@@ -81,10 +83,9 @@ Notes:
8183
rate expression. For example, in the reaction `k*A, B --> C`, there would be a
8284
red arrow from `A` to the reaction node. In `k*A, A+B --> C`, there would be
8385
red and black arrows from `A` to the reaction node.
84-
- The `interactive` flag sets the ability to interactively drag nodes and edges in the generated plot.
85-
Only allowed if `GLMakie` is the loaded Makie backend.
8686
"""
87-
function plot_speciesreaction_graph(rn::ReactionSystem; interactive = false)
87+
# TODO: update docs for interacting with plots. The `interactive` flag sets the ability to interactively drag nodes and edges in the generated plot. Only allowed if `GLMakie` is the loaded Makie backend.
88+
function Catalyst.plot_network(rn::ReactionSystem)
8889
srg = SRGraphWrap(rn)
8990
ns = length(species(rn))
9091
nodecolors = vcat([:skyblue3 for i in 1:ns],
@@ -103,38 +104,30 @@ function plot_speciesreaction_graph(rn::ReactionSystem; interactive = false)
103104
end
104105
edgecolors = [:black for i in 1:ne(srg)]
105106

106-
elist = Graphs.edges(srg)
107-
for i in 2:length(elist)
108-
if elist[i] == elist[i-1]
107+
num_e = ne(srg.g)
108+
for i in 1:length(srg.edgeorder)
109+
if srg.edgeorder[i] > num_e
109110
edgecolors[i] = :red
110111
insert!(edgelabels, i, "")
111112
end
112113
end
113114

114-
f, ax, p = graphplot(srg;
115+
graphplot(srg;
115116
edge_color = edgecolors,
116-
elabels = edgelabels,
117+
elabels = edgelabels,
117118
elabels_rotation = 0,
118-
ilabels = ilabels,
119+
ilabels = ilabels,
119120
node_color = nodecolors,
120121
node_size = nodesizes,
121122
arrow_shift = :end,
122123
arrow_size = 20,
123124
curve_distance_usage = true,
124125
curve_distance = gen_distances(srg)
125126
)
126-
127-
interactive && begin
128-
deregister_interaction!(ax, :rectanglezoom)
129-
register_interaction!(ax, :ndrag, NodeDrag(p))
130-
register_interaction!(ax, :edrag, EdgeDrag(p))
131-
end
132-
display(f)
133-
f
134127
end
135128

136129
"""
137-
ComplexGraph(rn::ReactionSystem; interactive=false)
130+
plot_complexes(rn::ReactionSystem; interactive=false)
138131
139132
Creates a GraphMakie plot of the [`ReactionComplex`](@ref)s in `rn`. Reactions
140133
correspond to arrows and reaction complexes to blue circles.
@@ -144,10 +137,8 @@ end
144137
parameter or a `Number`. i.e. `k, A --> B`.
145138
- Red arrows from complexes to complexes indicate reactions whose rate
146139
depends on species. i.e. `k*C, A --> B` for `C` a species.
147-
- The `interactive` flag sets the ability to interactively drag nodes and edges in the generated plot.
148-
Only allowed if `GLMakie` is the loaded Makie backend.
149140
"""
150-
function plot_complex_graph(rn::ReactionSystem; interactive = false)
141+
function Catalyst.plot_complexes(rn::ReactionSystem)
151142
img = incidencematgraph(rn)
152143
specs = species(rn); rxs = reactions(rn)
153144
edgecolors = [:black for i in 1:ne(img)]
@@ -161,7 +152,7 @@ function plot_complex_graph(rn::ReactionSystem; interactive = false)
161152
(!isempty(deps)) && (edgecolors[i] = :red)
162153
end
163154

164-
f, ax, p = graphplot(img;
155+
graphplot(img;
165156
edge_color = edgecolors,
166157
elabels = edgelabels,
167158
ilabels = complexlabels(rn),
@@ -170,14 +161,6 @@ function plot_complex_graph(rn::ReactionSystem; interactive = false)
170161
arrow_shift = :end,
171162
curve_distance = 0.2
172163
)
173-
174-
interactive && begin
175-
deregister_interaction!(ax, :rectanglezoom)
176-
register_interaction!(ax, :ndrag, NodeDrag(p))
177-
register_interaction!(ax, :edrag, EdgeDrag(p))
178-
end
179-
display(f)
180-
f
181164
end
182165

183166
function complexelem_tostr(e::Catalyst.ReactionComplexElement, specstrs)
@@ -199,9 +182,9 @@ function complexlabels(rn::ReactionSystem)
199182
if isempty(complex)
200183
push!(labels, "")
201184
elseif length(complex) == 1
202-
push!(labels, complexelemtostr(complex[1], specstrs))
185+
push!(labels, complexelem_tostr(complex[1], specstrs))
203186
else
204-
elems = map(c -> complexelemtostr(c, specstrs), complex)
187+
elems = map(c -> complexelem_tostr(c, specstrs), complex)
205188
str = reduce((e1, e2) -> *(e1, " + ", e2), @view elems[2:end]; init = elems[1])
206189
push!(labels, str)
207190
end

src/Catalyst.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ export hc_steady_states
167167
function make_si_ode end
168168
export make_si_ode
169169

170+
# GraphMakie
171+
function plot_network end
172+
function plot_petrinet end
173+
function plot_complexes end
174+
export plot_network, plot_complexes, plot_petrinet
175+
170176
### Spatial Reaction Networks ###
171177

172178
# Spatial reactions.

test/extensions/graphmakie.jl

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using Catalyst, GraphMakie, GLMakie
1+
using Catalyst, GraphMakie, GLMakie, Graphs
22
include("../test_networks.jl")
3+
34
# Test that speciesreactiongraph is generated correctly
45
let
56
brusselator = @reaction_network begin
@@ -11,7 +12,7 @@ let
1112

1213
srg = Catalyst.species_reaction_graph(brusselator)
1314
s = length(species(brusselator))
14-
edgel = Edge.([(s+1, 1),
15+
edgel = Graphs.Edge.([(s+1, 1),
1516
(1, s+2),
1617
(2, s+2),
1718
(s+2, 1),
@@ -45,19 +46,61 @@ let
4546
srg = Catalyst.species_reaction_graph(MAPK)
4647
@test nv(srg) == length(species(MAPK)) + length(reactions(MAPK))
4748
@test ne(srg) == 90
49+
50+
# Test that figures are generated properly.
51+
f = plot_network(MAPK)
52+
save("fig.png", f)
53+
@test isfile("fig.png")
54+
rm("fig.png")
55+
f = plot_network(brusselator)
56+
save("fig.png", f)
57+
@test isfile("fig.png")
58+
rm("fig.png")
59+
60+
f = plot_complexes(MAPK); save("fig.png", f)
61+
@test isfile("fig.png")
62+
rm("fig.png")
63+
f = plot_complexes(brusselator); save("fig.png", f)
64+
@test isfile("fig.png")
65+
rm("fig.png")
4866
end
4967

50-
# Test that rate edges are inferred correctly
68+
CGME = Base.get_extension(parentmodule(ReactionSystem), :CatalystGraphMakieExtension)
69+
# Test that rate edges are inferred correctly. We should see two for the following reaction network.
5170
let
71+
# Two rate edges, one to species and one to product
5272
rn = @reaction_network begin
5373
k, A --> B
5474
k * C, A --> C
5575
k * B, B --> C
5676
end
57-
srg = SRGraphWrap(rn)
77+
srg = CGME.SRGraphWrap(rn)
5878
s = length(species(rn))
59-
@test Edge(3, s+2) srg.rateedges
60-
@test Edge(2, s+3) srg.rateedges
79+
@test ne(srg) == 8
80+
@test Graphs.Edge(3, s+2) srg.rateedges
81+
@test Graphs.Edge(2, s+3) srg.rateedges
6182
# Since B is both a dep and a reactant
62-
@test count(==(Edge(2, s+3)), edges(srg)) == 2
83+
@test count(==(Graphs.Edge(2, s+3)), edges(srg)) == 2
84+
85+
f = plot_network(rn)
86+
save("fig.png", f)
87+
@test isfile("fig.png")
88+
rm("fig.png")
89+
f = plot_complexes(rn); save("fig.png", f)
90+
@test isfile("fig.png")
91+
rm("fig.png")
92+
93+
# Two rate edges, both to reactants
94+
rn = @reaction_network begin
95+
k, A --> B
96+
k * A, A --> C
97+
k * B, B --> C
98+
end
99+
srg = CGME.SRGraphWrap(rn)
100+
s = length(species(rn))
101+
@test ne(srg) == 8
102+
# Since A, B is both a dep and a reactant
103+
@test count(==(Graphs.Edge(1, s+2)), edges(srg)) == 2
104+
@test count(==(Graphs.Edge(2, s+3)), edges(srg)) == 2
63105
end
106+

0 commit comments

Comments
 (0)