Skip to content

Commit

Permalink
LatticeReactionSystem revamp
Browse files Browse the repository at this point in the history
  • Loading branch information
TorkelE committed Sep 12, 2023
1 parent e46e1ad commit ee755a2
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 34 deletions.
3 changes: 3 additions & 0 deletions src/Catalyst.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,7 @@ include("spatial_reaction_systems/lattice_reaction_systems.jl")
export LatticeReactionSystem
export spatial_species, vertex_parameters, edge_parameters

# spatial lattice ode systems.
include("spatial_reaction_systems/spatial_ODE_systems.jl")

end # module
57 changes: 31 additions & 26 deletions src/spatial_reaction_systems/lattice_reaction_systems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,41 @@ species(lrs::LatticeReactionSystem) = unique([species(lrs.rs); lrs.spat_species]
spatial_species(lrs::LatticeReactionSystem) = lrs.spat_species

Check warning on line 62 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L62

Added line #L62 was not covered by tests

# Get all parameters.
ModelingToolkit.parameters(lrs::LatticeReactionSystem) = unique([species(lrs.rs); lrs.edge_parameters])
ModelingToolkit.parameters(lrs::LatticeReactionSystem) = unique([parameters(lrs.rs); lrs.edge_parameters])

Check warning on line 65 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L65

Added line #L65 was not covered by tests
# Get all parameters which values are tied to vertexes (compartments).
vertex_parameters(lrs::LatticeReactionSystem) = setdiff(parameters(lrs), edge_parameters(lrs))

Check warning on line 67 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L67

Added line #L67 was not covered by tests
# Get all parameters which values are tied to edges (adjacencies).
edge_parameters(lrs::LatticeReactionSystem) = lrs.edge_parameters

Check warning on line 69 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L69

Added line #L69 was not covered by tests

# Gets the lrs name (same as rs name).
ModelingToolkit.nameof(lrs::LatticeReactionSystem) = nameof(lrs.rs)

Check warning on line 72 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L72

Added line #L72 was not covered by tests

# Checks if a lattice reaction system is a pure (linear) transport reaction system.
is_transport_system(lrs::LatticeReactionSystem) = all(typeof.(lrs.spatial_reactions) .== TransportReaction)

Check warning on line 75 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L75

Added line #L75 was not covered by tests

### Processes Input u0 & p ###

# Required to make symmapt_to_varmap to work.
function _symbol_to_var(lrs::LatticeReactionSystem, sym)
p_idx = findfirst(sym==p_sym for p_sym in ModelingToolkit.getname.(parameters(lrs)))
isnothing(p_idx) || return parameters(lrs)[p_idx]
s_idx = findfirst(sym==s_sym for s_sym in ModelingToolkit.getname.(species(lrs)))
isnothing(s_idx) || return species(lrs)[s_idx]
error("Could not find property parameter/species $sym in lattice reaction system.")

Check warning on line 85 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L80-L85

Added lines #L80 - L85 were not covered by tests
end

# From u0 input, extracts their values and store them in the internal format.
function lattice_process_u0(u0_in, u0_symbols, nV)
u0 = lattice_process_input(u0_in, u0_symbols, nV)
function lattice_process_u0(u0_in, u0_syms, nV)
u0 = lattice_process_input(u0_in, u0_syms, nV)
check_vector_lengths(u0, nV)
expand_component_values(u0, nV)

Check warning on line 92 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L89-L92

Added lines #L89 - L92 were not covered by tests
end

# From p input, splits it into diffusion parameters and compartment parameters, and store these in the desired internal format.
function lattice_process_p(p_in, p_comp_symbols, p_diff_symbols, lrs::LatticeReactionSystem)
pV_in, pE_in = split_parameters(p_in, p_comp_symbols, p_diff_symbols)
pV = lattice_process_input(pV_in, p_comp_symbols, lrs.nV)
pE = lattice_process_input(pE_in, p_diff_symbols, lrs.nE)
function lattice_process_p(p_in, p_vertex_syms, p_edge_syms, lrs::LatticeReactionSystem)
pV_in, pE_in = split_parameters(p_in, p_vertex_syms, p_edge_syms)
pV = lattice_process_input(pV_in, p_vertex_syms, lrs.nV)
pE = lattice_process_input(pE_in, p_edge_syms, lrs.nE)
lrs.init_digraph || foreach(idx -> duplicate_spat_params!(pE, idx, lrs), 1:length(pE))
check_vector_lengths(pV, lrs.nV)
check_vector_lengths(pE, lrs.nE)
Expand All @@ -106,12 +118,10 @@ function split_parameters(ps::Vector{<:Pair}, p_comp_symbols::Vector,
end

# If the input is given in a map form, the vector needs sorting and the first value removed.
function lattice_process_input(input::Vector{<:Pair}, symbols::Vector{Symbol}, args...)
(length(setdiff(Symbol.(first.(input)), symbols)) != 0) &&
error("Some input symbols are not recognised: $(setdiff(Symbol.(first.(input)), symbols)).")
sorted_input = sort(input;
by = p -> findfirst(ModelingToolkit.getname(p[1]) .== symbols))
return lattice_process_input(last.(sorted_input), symbols, args...)
function lattice_process_input(input::Vector{<:Pair}, syms::Vector{BasicSymbolic{Real}}, args...)
isempty(setdiff(first.(input), syms)) || error("Some input symbols are not recognised: $(setdiff(first.(input), syms)).")
sorted_input = sort(input; by = p -> findfirst(isequal(p[1]), syms))
return lattice_process_input(last.(sorted_input), syms, args...)

Check warning on line 124 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L121-L124

Added lines #L121 - L124 were not covered by tests
end
# Processes the input and gvies it in a form where it is a vector of vectors (some of which may have a single value).
function lattice_process_input(input::Matrix{<:Number}, args...)
Expand All @@ -125,7 +135,7 @@ function lattice_process_input(input::Vector{<:Any}, args...)
lattice_process_input([(val isa Vector{<:Number}) ? val : [val] for val in input],
args...)
end
lattice_process_input(input::Vector{<:Vector}, symbols::Vector{Symbol}, n::Int64) = input
lattice_process_input(input::Vector{<:Vector}, syms::Vector{BasicSymbolic{Real}}, n::Int64) = input
function check_vector_lengths(input::Vector{<:Vector}, n)
isempty(setdiff(unique(length.(input)), [1, n])) ||

Check warning on line 140 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L138-L140

Added lines #L138 - L140 were not covered by tests
error("Some inputs where given values of inappropriate length.")
Expand All @@ -141,27 +151,22 @@ end
vals_to_dict(syms::Vector, vals::Vector{<:Vector}) = Dict(zip(syms, vals))

Check warning on line 151 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L151

Added line #L151 was not covered by tests
# Produces a dictionary with all parameter values.
function param_dict(pV, pE, lrs)
merge(vals_to_dict(compartment_parameters(lrs), pV),
vals_to_dict(diffusion_parameters(lrs), pE))
merge(vals_to_dict(vertex_parameters(lrs), pV),

Check warning on line 154 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L153-L154

Added lines #L153 - L154 were not covered by tests
vals_to_dict(edge_parameters(lrs), pE))
end

# Computes the spatial rates and stores them in a format (Dictionary of species index to rates across all edges).
function compute_all_spatial_rates(pV::Vector{Vector{Float64}},
pE::Vector{Vector{Float64}},
lrs::LatticeReactionSystem)
function compute_all_spatial_rates(pV::Vector{Vector{Float64}}, pE::Vector{Vector{Float64}}, lrs::LatticeReactionSystem)
param_value_dict = param_dict(pV, pE, lrs)
return [s => Symbolics.value.(compute_spatial_rates(get_spatial_rate_law(s, lrs),
param_value_dict, lrs.nE))
for s in spatial_species(lrs)]
return [s => Symbolics.value.(compute_spatial_rates(get_spatial_rate_law(s, lrs), param_value_dict, lrs.nE)) for s in spatial_species(lrs)]

Check warning on line 161 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L159-L161

Added lines #L159 - L161 were not covered by tests
end
function get_spatial_rate_law(s::Symbolics.BasicSymbolic, lrs::LatticeReactionSystem)
rates = filter(sr -> isequal(ModelingToolkit.getname(s), sr.species_sym),
lrs.spatial_reactions)
function get_spatial_rate_law(s::BasicSymbolic{Real}, lrs::LatticeReactionSystem)
rates = filter(sr -> isequal(s, sr.species), lrs.spatial_reactions)
(length(rates) > 1) && error("Species $s have more than one diffusion reaction.") # We could allows several and simply sum them though, easy change.
return rates[1].rate

Check warning on line 166 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L163-L166

Added lines #L163 - L166 were not covered by tests
end
function compute_spatial_rates(rate_law::Num,

Check warning on line 168 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L168

Added line #L168 was not covered by tests
param_value_dict::Dict{Any, Vector{Float64}}, nE::Int64)
param_value_dict::Dict{SymbolicUtils.BasicSymbolic{Real}, Vector{Float64}}, nE::Int64)
relevant_parameters = Symbolics.get_variables(rate_law)
if all(length(param_value_dict[P]) == 1 for P in relevant_parameters)
return [

Check warning on line 172 in src/spatial_reaction_systems/lattice_reaction_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/lattice_reaction_systems.jl#L170-L172

Added lines #L170 - L172 were not covered by tests
Expand Down
17 changes: 12 additions & 5 deletions src/spatial_reaction_systems/spatial_ODE_systems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,16 @@ function DiffEqBase.ODEProblem(lrs::LatticeReactionSystem, u0_in, tspan,
p_in = DiffEqBase.NullParameters(), args...;
jac = true, sparse = jac, kwargs...)
is_transport_system(lrs) || error("Currently lattice ODE simulations only supported when all spatial reactions are transport reactions.")

Check warning on line 54 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L54

Added line #L54 was not covered by tests
u0 = lattice_process_u0(u0_in, ModelingToolkit.getname.(species(lrs)), lrs.nV)
pV, pD = lattice_process_p(p_in, Symbol.(compartment_parameters(lrs)),
Symbol.(edge_parameters(lrs)), lrs)

# Converts potential symmaps to varmaps.
u0_in = symmap_to_varmap(lrs, u0_in)
p_in = (p_in isa Tuple{<:Any,<:Any}) ? (symmap_to_varmap(lrs, p_in[1]),symmap_to_varmap(lrs, p_in[2])) : symmap_to_varmap(lrs, p_in)

Check warning on line 58 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L57-L58

Added lines #L57 - L58 were not covered by tests

# Converts u0 and p to Vector{Vector{Float64}} form.
u0 = lattice_process_u0(u0_in, species(lrs), lrs.nV)
pV, pD = lattice_process_p(p_in, vertex_parameters(lrs), edge_parameters(lrs), lrs)

Check warning on line 62 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L61-L62

Added lines #L61 - L62 were not covered by tests

# Creates ODEProblem.
ofun = build_odefunction(lrs, pV, pD, jac, sparse)
return ODEProblem(ofun, u0, tspan, pV, args...; kwargs...)

Check warning on line 66 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L65-L66

Added lines #L65 - L66 were not covered by tests
end
Expand Down Expand Up @@ -100,13 +107,13 @@ function build_jac_prototype(ns_jac_prototype::SparseMatrixCSC{Float64, Int64},
local_elements = in(s, spat_species) *

Check warning on line 107 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L107

Added line #L107 was not covered by tests
(length(lrs.lattice.fadjlist[comp]) + only_spat[s])
spatial_elements = -(ns_jac_prototype.colptr[(s + 1):-1:s]...)
J_colptr[col_idx + 1] = J_colptr[col_idx] + local_elements + spatial_elements_elements
J_colptr[col_idx + 1] = J_colptr[col_idx] + local_elements + spatial_elements

Check warning on line 110 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L109-L110

Added lines #L109 - L110 were not covered by tests

# Row values.
rows = ns_jac_prototype.rowval[ns_jac_prototype.colptr[s]:(ns_jac_prototype.colptr[s + 1] - 1)] .+

Check warning on line 113 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L113

Added line #L113 was not covered by tests
(comp - 1) * lrs.nS
if in(s, spat_species)

Check warning on line 115 in src/spatial_reaction_systems/spatial_ODE_systems.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_ODE_systems.jl#L115

Added line #L115 was not covered by tests
# Finds the location of the spatial_elements elements, and inserts the elements from the non-spatial part into this.
# Finds the location of the spatial_elements, and inserts the elements from the non-spatial part into this.
spatial_rows = (lrs.lattice.fadjlist[comp] .- 1) .* lrs.nS .+ s
split_idx = isempty(rows) ? 1 : findfirst(spatial_rows .> rows[1])
isnothing(split_idx) && (split_idx = length(spatial_rows) + 1)
Expand Down
6 changes: 3 additions & 3 deletions src/spatial_reaction_systems/spatial_reactions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ ModelingToolkit.parameters(tr::TransportReaction) = convert(Vector{BasicSymbolic
# Gets the species in a transport reaction.
spatial_species(tr::TransportReaction) = [tr.species]

Check warning on line 63 in src/spatial_reaction_systems/spatial_reactions.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_reactions.jl#L63

Added line #L63 was not covered by tests

# Checks that a trnasport reaction is valid for a given reaction system.
# Checks that a transport reaction is valid for a given reaction system.
function check_spatial_reaction_validity(rs::ReactionSystem, tr::TransportReaction)

Check warning on line 66 in src/spatial_reaction_systems/spatial_reactions.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_reactions.jl#L66

Added line #L66 was not covered by tests
# Checks that the rate does not depend on species.
isempty(intersect(ModelingToolkit.getname.(species(rs)), ModelingToolkit.getname.(Symbolics.get_variables(tr.rate)))) || error("The following species were used in rates of a transport reactions: $(setdiff(ModelingToolkit.getname(species(rs)), ModelingToolkit.getname(Symbolics.get_variables(tr.rate)))).")

Check warning on line 68 in src/spatial_reaction_systems/spatial_reactions.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_reactions.jl#L68

Added line #L68 was not covered by tests
# Checks that the species does not exist in the system with different metadata.
any([isequal(tr.species, s) && isequal(tr.species.metadata, s.metadata) for s in species(rs)]) || error("A transport reaction used a species ($(tr.species)) with metadata not matching its lattice reaction system. Please fetch this species from the reaction system and used in transport reaction creation.")
any([isequal(rs_p, tr_p) && isequal(rs_p.metadata, tr_p.metadata) for rs_p in parameters(rs), tr_p in Symbolics.get_variables(tr.rate)]) || error("A transport reaction used a parameter with metadata not matching its lattice reaction system. Please fetch this parameter from the reaction system and used in transport reaction creation.")
any([isequal(tr.species, s) && !isequal(tr.species.metadata, s.metadata) for s in species(rs)]) && error("A transport reaction used a species, $(tr.species), with metadata not matching its lattice reaction system. Please fetch this species from the reaction system and used in transport reaction creation.")
any([isequal(rs_p, tr_p) && !isequal(rs_p.metadata, tr_p.metadata) for rs_p in parameters(rs), tr_p in Symbolics.get_variables(tr.rate)]) && error("A transport reaction used a parameter with metadata not matching its lattice reaction system. Please fetch this parameter from the reaction system and used in transport reaction creation.")

Check warning on line 71 in src/spatial_reaction_systems/spatial_reactions.jl

View check run for this annotation

Codecov / codecov/patch

src/spatial_reaction_systems/spatial_reactions.jl#L70-L71

Added lines #L70 - L71 were not covered by tests
end

### Utility ###
Expand Down

0 comments on commit ee755a2

Please sign in to comment.