Commit 3ae6fbff authored by Miroslav Kratochvil's avatar Miroslav Kratochvil Committed by Miroslav Kratochvil
Browse files

fix API of screen() to avoid unbounded type parameters

parent 0a220c9e
...@@ -93,7 +93,7 @@ function flux_variability_analysis( ...@@ -93,7 +93,7 @@ function flux_variability_analysis(
end, end,
], ],
), ),
args = [-reactions reactions], args = [(x,) for x in [-reactions reactions]],
analysis = (_, opt_model, ridx) -> _max_variability_flux(opt_model, ridx, ret), analysis = (_, opt_model, ridx) -> _max_variability_flux(opt_model, ridx, ret),
workers = workers, workers = workers,
) )
......
""" """
_check_screen_mods_args(mods, args, modsname) _screen_args(argtuple, kwargtuple, modsname)
Internal helper to check the presence and shape of modification and argument Internal helper to check the presence and shape of modification and argument
arrays in [`screen`](@ref) and pals. arrays in [`screen`](@ref) and pals.
""" """
function _check_screen_mods_args( function _screen_args(argtuple, kwargtuple, modsname)
mods::Maybe{Array{V,N}},
args::Maybe{Array{A,N}}, mods = get(kwargtuple, modsname, nothing)
modsname, args = get(kwargtuple, :args, nothing)
) where {V,A,N}
if isnothing(mods) if isnothing(mods)
if isnothing(args) if isnothing(args)
throw( throw(
DomainError( DomainError(args, "at least one of `$modsname` and `args` must be defined"),
args,
"at least one of `$modsname` and `args` must be non-empty",
),
) )
end end
([[] for _ in args], Array{A,N}(args)) return NamedTuple{(modsname,)}(Ref([[] for _ in args]))
elseif isnothing(args) elseif isnothing(args)
(Array{V,N}(mods), [() for _ in mods]) return (args = [() for _ in mods],)
else else
if size(mods) != size(args) if size(mods) != size(args)
throw( throw(
...@@ -31,17 +28,18 @@ function _check_screen_mods_args( ...@@ -31,17 +28,18 @@ function _check_screen_mods_args(
), ),
) )
end end
return ()
end end
end end
""" """
function screen( screen(
model::MetabolicModel; model::MetabolicModel;
variants::Maybe{Array{V,N}} = nothing, variants::Array{Vector}, N},
analysis, analysis::Function,
args::Maybe{Array{A,N}} = nothing, args::Array{Vector{Tuple}, N},
workers = [myid()], workers = [myid()],
)::Array where {V<:AbstractVector,A,N} )::Array where {N}
Take an array of model-modifying function vectors in `variants`, and execute Take an array of model-modifying function vectors in `variants`, and execute
the function `analysis` on all variants of the `model` specified by `variants`. the function `analysis` on all variants of the `model` specified by `variants`.
...@@ -79,6 +77,9 @@ JuMP models that contain pointers to allocated C structures (such as ...@@ -79,6 +77,9 @@ JuMP models that contain pointers to allocated C structures (such as
[`flux_balance_analysis`](@ref) used with `GLPK` or `Gurobi` otimizers) will [`flux_balance_analysis`](@ref) used with `GLPK` or `Gurobi` otimizers) will
generally not in this context. generally not in this context.
Note: this function is a thin argument-handling wrapper around
[`_screen_impl`](@ref).
# Example # Example
``` ```
function reverse_reaction(i::Int) function reverse_reaction(i::Int)
...@@ -91,31 +92,43 @@ end ...@@ -91,31 +92,43 @@ end
m = load_model(CoreModel, "e_coli_core.xml") m = load_model(CoreModel, "e_coli_core.xml")
screen_variants(m, screen(m,
[ variants = [
[reverse_reaction(5)], [reverse_reaction(5)],
[reverse_reaction(3), reverse_reaction(6)] [reverse_reaction(3), reverse_reaction(6)]
], ],
mod -> mod.S[:,3]) # observe the changes in S analysis = mod -> mod.S[:,3]) # observe the changes in S
screen_variants(m, screen(m,
[ variants = [
[reverse_reaction(5)], [reverse_reaction(5)],
[reverse_reaction(3), reverse_reaction(6)] [reverse_reaction(3), reverse_reaction(6)]
], ],
mod -> flux_balance_analysis_vec(mod, GLPK.Optimizer)) # run analysis analysis = mod -> flux_balance_analysis_vec(mod, GLPK.Optimizer))
``` ```
""" """
function screen( screen(args...; kwargs...) =
_screen_impl(args...; kwargs..., _screen_args(args, kwargs, :variants)...)
"""
_screen_impl(
model::MetabolicModel;
variants::Array{Vector, N},
analysis::Function,
args::Array{Tuple, N},
workers = [myid()],
)::Array where {N}
The actual implementation of [`screen`](@ref).
"""
function _screen_impl(
model::MetabolicModel; model::MetabolicModel;
variants::Maybe{Array{V,N}} = nothing, variants::Array{V,N},
analysis, analysis,
args::Maybe{Array{A,N}} = nothing, args::Array{A,N},
workers = [myid()], workers = [myid()],
)::Array where {V<:AbstractVector,A,N} )::Array where {V<:AbstractVector,A,N}
(variants, args) = _check_screen_mods_args(variants, args, :variants)
map(fetch, save_at.(workers, :cobrexa_screen_variants_model, Ref(model))) map(fetch, save_at.(workers, :cobrexa_screen_variants_model, Ref(model)))
map(fetch, save_at.(workers, :cobrexa_screen_variants_analysis_fn, Ref(analysis))) map(fetch, save_at.(workers, :cobrexa_screen_variants_analysis_fn, Ref(analysis)))
map(fetch, get_from.(workers, Ref(:(precache!(cobrexa_screen_variants_model))))) map(fetch, get_from.(workers, Ref(:(precache!(cobrexa_screen_variants_model)))))
...@@ -199,15 +212,15 @@ function _screen_optmodel_item((mods, args)) ...@@ -199,15 +212,15 @@ function _screen_optmodel_item((mods, args))
end end
""" """
function screen_optmodel_modifications( screen_optmodel_modifications(
model::MetabolicModel, model::MetabolicModel,
optimizer; optimizer;
common_modifications::V, common_modifications::Vector = [],
modifications::Maybe{Array{V,N}} = nothing, modifications::Array{Vector,N},
args::Maybe{Array{T,N}} = nothing, args::Array{Vector{Tuple},N},
analysis = screen_optimize_objective, analysis::Function,
workers = [myid()], workers = [myid()],
) where {V<:AbstractVector,T<:Tuple,N} ) where N
Screen multiple modifications of the same optimization model. Screen multiple modifications of the same optimization model.
...@@ -230,18 +243,38 @@ have 2 base parameters (as opposed to 1 with [`screen`](@ref)): first is the ...@@ -230,18 +243,38 @@ have 2 base parameters (as opposed to 1 with [`screen`](@ref)): first is the
`model` (carried through as-is), second is the prepared JuMP optimization model `model` (carried through as-is), second is the prepared JuMP optimization model
that may be modified and acted upon. As an example, you can use modification that may be modified and acted upon. As an example, you can use modification
[`change_constraint`](@ref) and analysis [`screen_optimize_objective`](@ref). [`change_constraint`](@ref) and analysis [`screen_optimize_objective`](@ref).
Note: This function is a thin argument-handling wrapper around
[`_screen_optmodel_modifications_impl`](@ref).
""" """
function screen_optmodel_modifications( screen_optmodel_modifications(args...; kwargs...) = _screen_optmodel_modifications_impl(
args...;
kwargs...,
_screen_args(args, kwargs, :modifications)...,
)
"""
_screen_optmodel_modifications_impl(
model::MetabolicModel, model::MetabolicModel,
optimizer; optimizer;
common_modifications::Vector = [], common_modifications::Vector = [],
modifications::Maybe{Array{V,N}} = nothing, modifications::Array{Vector,N},
args::Maybe{Array{A,N}} = nothing, args::Array{Tuple,N},
analysis::Any, analysis::Function,
workers = [myid()], workers = [myid()],
) where {V<:AbstractVector,A,N} ) where N
(modifications, args) = _check_screen_mods_args(modifications, args, :modifications) The actual implementation of [`screen_optmodel_modifications`](@ref).
"""
function _screen_optmodel_modifications_impl(
model::MetabolicModel,
optimizer;
common_modifications::VF = [],
modifications::Array{V,N},
args::Array{A,N},
analysis::Function,
workers = [myid()],
)::Array where {V<:AbstractVector,VF<:AbstractVector,A,N}
map( map(
fetch, fetch,
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
# nothing to analyze # nothing to analyze
@test_throws DomainError screen(m; analysis = identity) @test_throws DomainError screen(m; analysis = identity)
# array dimensionalities must match (this is actually caught by typechecker) # array dimensionalities must match
@test_throws MethodError screen( @test_throws DomainError screen(
m; m;
analysis = identity, analysis = identity,
variants = [[], []], variants = [[], []],
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment