Commit 271ae55e authored by Miroslav Kratochvil's avatar Miroslav Kratochvil Committed by Miroslav Kratochvil
Browse files

fix API of screen() to avoid unbounded type parameters

parent 96ff9e23
...@@ -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,15 +28,16 @@ function _check_screen_mods_args( ...@@ -31,15 +28,16 @@ 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{V,N}, # defaults to an array of identities
analysis, analysis,
args::Maybe{Array{A,N}} = nothing, args::Array{A,N}, # defaults to an array of empty argument lists
workers = [myid()], workers = [myid()],
)::Array where {V<:AbstractVector,A,N} )::Array where {V<:AbstractVector,A,N}
...@@ -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,30 +92,42 @@ end ...@@ -91,30 +92,42 @@ 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; 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) The actual implementation of [`screen`](@ref).
"""
function _screen_impl(
model::MetabolicModel;
variants::Array{V,N},
analysis,
args::Array{A,N},
workers = [myid()],
)::Array where {V<:AbstractVector,A,N}
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)))
...@@ -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::VF = [],
modifications::Maybe{Array{V,N}} = nothing, modifications::Array{V,N}, # defaults to an array with no modifications
args::Maybe{Array{T,N}} = nothing, args::Array{A,N}, # defaults to an array of empty argument lists
analysis = screen_optimize_objective, analysis::Function,
workers = [myid()], workers = [myid()],
) where {V<:AbstractVector,T<:Tuple,N} )::Array where {V<:AbstractVector,VF<:AbstractVector,A,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::VF = [],
modifications::Maybe{Array{V,N}} = nothing, modifications::Array{V,N},
args::Maybe{Array{A,N}} = nothing, args::Array{A,N},
analysis::Any, analysis::Function,
workers = [myid()], workers = [myid()],
) where {V<:AbstractVector,A,N} )::Array where {V<:AbstractVector,VF<:AbstractVector,A,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