diff --git a/Project.toml b/Project.toml index 70a5f85..f863cef 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "AbstractImageReconstruction" uuid = "a4b4fdbf-6459-4ec9-990d-77e1fa24a91b" authors = ["nHackel and contributors"] -version = "0.3.2" +version = "0.3.5" [deps] LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" diff --git a/src/RecoPlans/Cache.jl b/src/RecoPlans/Cache.jl index 9bb0c84..976a50d 100644 --- a/src/RecoPlans/Cache.jl +++ b/src/RecoPlans/Cache.jl @@ -4,12 +4,15 @@ Base.@kwdef mutable struct ProcessResultCache{P <: AbstractImageReconstructionPa const maxsize::Int64 = 1 cache::LRU{UInt64, Any} = LRU{UInt64, Any}(maxsize = maxsize) end -function process(algo::Union{A, Type{<:A}}, param::ProcessResultCache, inputs...) where {A<:AbstractImageReconstructionAlgorithm} +ProcessResultCache(param::AbstractImageReconstructionParameters; kwargs...) = ProcessResultCache(;param, kwargs...) +process(algo::A, param::ProcessResultCache, inputs...) where {A <: AbstractImageReconstructionAlgorithm} = hashed_process(algo, param, inputs...) +process(algoT::Type{<:A}, param::ProcessResultCache, inputs...) where {A <: AbstractImageReconstructionAlgorithm} = hashed_process(algoT, param, inputs...) + +function hashed_process(algo, param::ProcessResultCache, inputs...) id = hash(param.param, hash(inputs, hash(algo))) result = get!(param.cache, id) do process(algo, param.param, inputs...) end - param.cache[id] = result return result end @@ -53,9 +56,15 @@ function Base.getproperty(plan::RecoPlan{<:ProcessResultCache}, name::Symbol) end end -function validvalue(plan, ::Type{T}, value::RecoPlan{<:ProcessResultCache}) where T + +function validvalue(plan, union::Type{Union{T, ProcessResultCache{<:T}}}, value::RecoPlan{ProcessResultCache}) where T innertype = value.param isa RecoPlan ? typeof(value.param).parameters[1] : typeof(value.param) - return ProcessResultCache{<:innertype} <: T + return ProcessResultCache{<:innertype} <: union +end + +function validvalue(plan, union::UnionAll, value::RecoPlan{ProcessResultCache}) + innertype = value.param isa RecoPlan ? typeof(value.param).parameters[1] : typeof(value.param) + return ProcessResultCache{<:innertype} <: union end function validvalue(plan, union::UnionAll, value::RecoPlan{<:ProcessResultCache}) diff --git a/src/RecoPlans/RecoPlans.jl b/src/RecoPlans/RecoPlans.jl index 3294bd2..01d573f 100644 --- a/src/RecoPlans/RecoPlans.jl +++ b/src/RecoPlans/RecoPlans.jl @@ -96,6 +96,7 @@ validvalue(plan, ::Type{T}, value::RecoPlan{<:T}) where T = true validvalue(plan, t::UnionAll, ::RecoPlan{T}) where T = T <: t || T <: Base.typename(t).wrapper # Last case doesnt work for Union{...} that is a UnionAll, such as ProcessCache Unio validvalue(plan, t::Type{Union}, value) = validvalue(plan, t.a, value) || validvalue(plan, t.b, value) validvalue(plan, t, value) = false +validvalue(plan, ::Type{arrT}, value::AbstractArray) where {T, arrT <: AbstractArray{T}} = all(x -> validvalue(plan, T, x), value) #X <: t || X <: RecoPlan{<:t} || ismissing(x) @@ -111,7 +112,7 @@ end export setAll! function setAll!(plan::RecoPlan{T}, name::Symbol, x) where {T<:AbstractImageReconstructionParameters} fields = getfield(plan, :values) - nestedPlans = filter(entry -> isa(last(entry), RecoPlan), fields) + nestedPlans = filter(entry -> isa(last(entry), RecoPlan) || isa(last(entry), AbstractArray{<:RecoPlan}), fields) for (key, nested) in nestedPlans key != name && setAll!(nested, name, x) end @@ -123,6 +124,7 @@ function setAll!(plan::RecoPlan{T}, name::Symbol, x) where {T<:AbstractImageReco end end end +setAll!(plans::AbstractArray{<:RecoPlan}, name::Symbol, x) = foreach(p -> setAll!(p, name, x), plans) setAll!(plan::RecoPlan{<:AbstractImageReconstructionAlgorithm}, name::Symbol, x) = setAll!(plan.parameter, name, x) function setAll!(plan; kwargs...) for key in keys(kwargs) @@ -181,13 +183,14 @@ Base.ismissing(plan::RecoPlan, name::Symbol) = ismissing(getfield(plan, :values) export build function build(plan::RecoPlan{T}) where {T<:AbstractImageReconstructionParameters} fields = copy(getfield(plan, :values)) - nestedPlans = filter(entry -> isa(last(entry), RecoPlan), fields) + nestedPlans = filter(entry -> isa(last(entry), RecoPlan) || isa(last(entry), AbstractArray{<:RecoPlan}), fields) for (name, nested) in nestedPlans fields[name] = build(nested) end fields = filter(entry -> !ismissing(last(entry)), fields) return T(;fields...) end +build(plans::AbstractArray{<:RecoPlan}) = map(build, plans) function build(plan::RecoPlan{T}) where {T<:AbstractImageReconstructionAlgorithm} parameter = build(plan[:parameter]) return T(parameter) diff --git a/src/RecoPlans/Serialization.jl b/src/RecoPlans/Serialization.jl index fb2beaf..a0cf71a 100644 --- a/src/RecoPlans/Serialization.jl +++ b/src/RecoPlans/Serialization.jl @@ -6,7 +6,13 @@ function plandir(m::Module) return @get_scratch!(string(m)) end end -planpath(m::Module, name::AbstractString) = joinpath(plandir(m), string(name, ".toml")) +function planpath(m::Module, name::AbstractString) + if m != AbstractImageReconstruction && hasproperty(m, :planpath) + return getproperty(m, :planpath)(name) + else + return joinpath(plandir(m), string(name, ".toml")) + end +end export savePlan savePlan(filename::AbstractString, plan::RecoPlan) = toTOML(filename, plan) @@ -54,7 +60,7 @@ function createModuleDataTypeDict(modules::Vector{Module}) try t = getfield(mod, field) if t isa DataType || t isa UnionAll || t isa Function - typeDict[string(t)] = t + typeDict[string(field)] = t end catch end @@ -93,6 +99,9 @@ function loadPlan!(plan::RecoPlan{T}, dict::Dict{String, Any}, modDict) where {T if t <: AbstractImageReconstructionAlgorithm || t <: AbstractImageReconstructionParameters param = loadPlan!(dict[key], modDict) parent!(param, plan) + elseif t <: Vector{<:AbstractImageReconstructionAlgorithm} || t <: Vector{<:AbstractImageReconstructionParameters} + param = map(x-> loadPlan!(x, modDict), dict[key]) + foreach(p -> parent!(p, plan), param) else param = loadPlanValue(T, name, t, dict[key], modDict) end