API for Solvers

This page contains documentation of the public API of the AbstractImageReconstruction. In the Julia REPL one can access this documentation by entering the help mode with ?

Algorithm and Parameters

AbstractImageReconstruction.AbstractImageReconstructionParametersType
AbstractImageReconstructionParameters

Abstract type for image reconstruction parameters. An algorithm consists of one or more process steps, each can have its own parameters. Parameters can be arbitrarily nested. Parameters are callable and can be invoked directly on algorithm instances:

result = param(algo, inputs...)

or a type-based implementation:

result = param(typeof(algo), inputs...)

Interface

Implement one of:

  • (param::MyParameters)(::Type{<:MyAlgorithm}, inputs...) for type-based processing
  • (param::MyParameters)(algo::MyAlgorithm, inputs...) for instance-based processing (defaults to type-based)
source
AbstractImageReconstruction.@reconstructionMacro
@reconstruction [constructor={true, false}] [hash={true, false}] struct AlgoName{P <: Params} <: AbstractBase
  @parameter parameter::P
  field::Type = default
  field = default
  @init hook!(algo)
end

Define a reconstruction algorithm struct with all boilerplate automatically generated.

The @reconstruction macro generates:

  • A mutable struct with algorithm infrastructure fields (channel for FIFO buffering)
  • A simple constructor that accepts only the parameter (if constructor=true)
  • Implementation of all interface methods: put!, take!, isready, wait, lock, unlock
  • A hash method (if hash=true)

Configuration Options

  • constructor=true (default) - Auto-generate a simple constructor
  • constructor=false - No constructor generated (write custom constructor)
  • hash=true (default) - Generate a hash method
  • hash=false - Do not generate a hash method

Syntax

Required

  • @parameter parameter::ParameterType - The main parameter field (immutable)

Optional State Fields

  • field::Type = default - Typed field with default value
  • field = default - Untyped field with default value

Optional Hooks

  • @init hook!(algo) - Custom initialization hook after construction

Examples

# Simple algorithm with default constructor
@reconstruction mutable struct MyAlgorithm <: AbstractImageReconstructionAlgorithm
  @parameter params::MyParameters
  state::Vector{Float64} = Float64[]
  counter::Int = 0
end

# Algorithm with custom initialization
@reconstruction mutable struct AlgorithmWithInit <: CustomBase
  @parameter params::MyParameters
  cache::Dict{String, Any} = Dict()

  @init function setup!(algo::AlgorithmWithInit)
    algo.cache["initialized"] = true
  end
end

# Algorithm without auto-generated constructor
@reconstruction constructor=false mutable struct CustomConstructorAlgorithm
  @parameter params::MyParameters
  state::Vector{Float64}
end
function CustomConstructorAlgorithm(params)
  # Custom initialization logic
  state = ...
  algo = CustomConstructorAlgorithm(params, state, @reconstruction_internals CustomConstructorAlgorithm)
  # ... more setup ...
  return algo
end
source
AbstractImageReconstruction.@parameterMacro
@parameter [constructor={true,false}] [hash={true,false}] (mutable) struct Name{...} <: AbstractImageReconstructionParameters
  field1::Type1 [= default1]
  field2::Type2 [= default2]
  ...
  @validate begin
    @assert field1 >= ... "message"
    ...
  end
end

Define a parameter struct for image reconstruction algorithms.

The @parameter macro generates:

  • A struct with the specified fields
  • A keyword constructor for easy instantiation: Name(field1=val1, field2=val2) with (optional) validation
  • A validate! function for parameter validation (if @validate is used)

Configuration Options

  • constructor=true (default) - Auto-generate a keyword constructor
  • constructor=false - No keyword constructor generated (write custom constructor)
  • Note: When using constructor=false with fields that have default values (e.g., field::Int = 10), those defaults are NOT available via keyword arguments. Handle defaults in your custom constructor.
  • Note: When using constructor=false with @validate, you must manually call validate! in your custom constructor.
  • hash=true (default) - Generate a hash method for the parameter type
  • hash=false - Do not generate a hash method

Syntax

Required

  • field::Type - Required field with type annotation
  • field::Type = default - Optional field with default value

Optional Validation

  • @validate - Block of validation assertions

Examples

# Simple parameter with validation
@parameter struct MyParameters <: AbstractImageReconstructionParameters
  iterations::Int = 10
  tolerance::Float64 = 1e-6
  @validate begin
    @assert iterations > 0 "iterations must be positive"
    @assert tolerance > 0 "tolerance must be positive"
  end
end

# Parameter without auto-generated constructor
@parameter constructor=false struct CustomParams
  field::Int
  @validate begin
    @assert field > 0 "field must be positive"
  end
end

function CustomParams(;field::Int)
  params = CustomParams(field)
  validate!(params)  # Must call manually when constructor=false
  return params
end
source
AbstractImageReconstruction.@chainMacro
@chain [constructor={true,false}] [hash={true,false}] struct Name{...} <: AbstractImageReconstructionParameters
  step1::P1 [= default1]
  step2::P2 [= default2]
  ...
  @validate @assert condition "message"
end

Define a composite parameter type that chains multiple processing steps.

The @chain macro generates:

  • A struct with the specified field parameters
  • A keyword constructor for easy instantiation
  • A validate! function (if @validate is used)
  • Call methods that chain the step parameters sequentially

When called, the composite parameter executes each step in order:

result = params.step1(algo, inputs...)
result = params.step2(algo, result...)
...
return result

Configuration Options

  • constructor=true (default) - Auto-generate a keyword constructor
  • constructor=false - No keyword constructor generated (write custom constructor)
  • Note: When using constructor=false with fields that have default values (e.g., step::Params = Params()), those defaults are NOT available via keyword arguments. Handle defaults in your custom constructor.
  • Note: When using constructor=false with @validate, you must manually call validate! in your custom constructor.
  • hash=true (default) - Generate a hash method for the parameter type
  • hash=false - Do not generate a hash method

Syntax

Required

  • step1::P1 - First processing step parameter type
  • step2::P2 - Second processing step parameter type
  • Each field should be a parameter type that implements (param, algo, inputs...)

Optional

  • @validate - Block of validation assertions

Examples

# Chain preprocessing and reconstruction steps
@chain struct CompositeParameters <: AbstractImageReconstructionParameters
  pre::RadonPreprocessingParameters
  reco::RadonBackprojectionParameters
end

# Chain without auto-generated constructor
@chain constructor=false struct CustomChain <: AbstractImageReconstructionParameters
  step1::StepParams
  @validate begin
    @assert step1.value >= 0 "step value must be non-negative"
  end
end

function CustomChain(;step1::StepParams)
  chain = CustomChain(step1)
  validate!(chain)  # Must call manually when constructor=false
  return chain
end
source
AbstractImageReconstruction.reconstructFunction
reconstruct(algo::T, u) where {T<:AbstractImageReconstructionAlgorithm}

Reconstruct an image from input u using algorithm algo. The àlgo will be locked until the result is available or an error occurs.

source
AbstractImageReconstruction.validate!Function
validate!(param::AbstractImageReconstructionParameters)

Validate a parameter object independent of any specific algorithm.

This is the default, algorithm-agnostic validation method. Concrete parameter types can specialize this method to enforce internal invariants, e.g.:

function validate!(p::MyParams)
    @assert p.iterations > 0 "iterations must be positive"
    @assert length(p.reg) > 0 "regularization vector must not be empty"
    return p
end

By default, this method is a no-op and simply returns param

source
validate!(algo, param::AbstractImageReconstructionParameters)

Validate a parameter object in the context of a specific reconstruction algorithm algo.

source

The above macros and functions are all that is required to implement when using the provided macros. For custom structs without the macros, it's also necessary to implement the following functions:

Base.put!Method
put!(algo::AbstractImageReconstructionAlgorithm, inputs...)

Perform image reonstruction with algorithm algo on given ìnputs. Depending on the algorithm this might block. Result is stored and can be retrieved with take!.

source
Base.take!Method
take!(algo::AbstractImageReconstructionAlgorithm)

Remove and return a stored result from the algorithm algo. Blocks until a result is available.

source
Base.lockMethod
lock(algo::AbstractImageReconstructionAlgorithm)

Acquire a lock on the algorithm algo. If the lock is already acquired, wait until it is released.

Each lock must be matched with a unlock.

source
Base.unlockMethod
unlock(algo::AbstractImageReconstructionAlgorithm)

Release a lock on the algorithm algo.

source
Base.isreadyMethod
isready(algo::AbstractImageReconstructionAlgorithm)

Determine if the algorithm algo has a result available.

source
Base.waitMethod
wait(algo::AbstractImageReconstructionAlgorithm)

Wait for a result to be available from the specified algo.

source
AbstractImageReconstruction.parameterFunction
parameter(algo::AbstractImageReconstructionAlgorithm)

Return the parameters of the algorithm algo.

source
parameter(param::AbstractUtilityReconstructionParameters)

Return the wrapped parameter. Can themselves be utility parameters again

source

RecoPlan

AbstractImageReconstruction.toPlanFunction
toPlan(param::Union{AbstractImageReconstructionParameters, AbstractImageReconstructionAlgorithm})

Convert an AbstractImageReconstructionParameters or AbstractImageReconstructionAlgorithm to a (nested) RecoPlan.

source
AbstractImageReconstruction.buildFunction
build(plan::RecoPlan{T}) where {T}

Recursively build a plan from a RecoPlan by converting all properties to their actual values using keyword argument constructors.

source
Base.propertynamesMethod
propertynames(plan::RecoPlan{T}) where {T}

Return a tupel of configurable properties of T. Unlike propertynames(T) this does not include properties starting with _.

source
Base.getpropertyMethod
getproperty(plan::RecoPlan{T}, name::Symbol) where {T}

Get the property name of plan. Equivalent to plan.name.

source
Base.getindexMethod
getindex(plan::RecoPlan{T}, name::Symbol) where {T}

Return the Observable for the name property of plan. Equivalent to plan[name].

source
Base.setproperty!Method
setproperty!(plan::RecoPlan{T}, name::Symbol, x::X) where {T, X}

Set the property name of plan to x. Equivalent to plan.name = x. Triggers callbacks attached to the property.

source
AbstractImageReconstruction.setAll!Function
setAll!(plan::RecoPlan{T}, name::Symbol, x) where {T<:AbstractImageReconstructionParameters}

Recursively set the property name of each nested RecoPlan of plan to x.

source
setAll!(plan::AbstractRecoPlan; kwargs...)

Call setAll! with each given keyword argument.

source
setAll!(plan::AbstractRecoPlan, dict::Union{Dict{Symbol, Any}, Dict{String, Any}})

Call setAll! with each entries of the dict.

source
AbstractImageReconstruction.clear!Function
clear!(plan::RecoPlan{T}, preserve::Bool = true) where {T<:AbstractImageReconstructionParameters}

Clear all properties of plan. If preserve is true, nested RecoPlans are preserved.

source
Base.ismissingMethod
ismissing(plan::RecoPlan, name::Symbol)

Indicate if the property name of plan is missing.

source
Observables.onMethod
on(f, plan::RecoPlan, property::Symbol; kwargs...)

Adds function f as listener to property of plan. The function is called whenever the property is changed with setproperty!.

source
Observables.offMethod
off(plan::RecoPlan, property::Symbol, f)

Remove f from the listeners of property of plan.

source
AbstractImageReconstruction.RecoPlanStyleType
RecoPlanStyle

Style for serializing RecoPlan and related types using StructUtils.

This style customizes the serialization and deserialization of reconstruction plans, parameters, and algorithms. It uses StructUtils.lower for serialization and StructUtils.lift for deserialization, with special handling for metadata preservation.

Serialization (lower)

The StructUtils.lower method for RecoPlanStyle:

  • For RecoPlans: stores _module, _type tags and serializes nested plans
  • For parameters/algorithms: applies default StructUtils.lower from FIELD_STYLE
  • Custom types can be handled by defining StructUtils.lower(::RecoPlanStyle, ::Type{T})
  • Array elements are recursively lowered

Deserialization (lift/make)

Deserialization has two layers:

  1. lift: Converts TOML values back to Julia types
    • Used for simple types: Symbol, Enum, AbstractArray, Type, Complex
    • Union types handled by deserializeUnion which tries each member
    • Users can define custom StructUtils.lift(::RecoPlanStyle, ::Type{T}, source)
  2. make/make!: Reconstructs RecoPlan instances
    • Only needed when the plan structure itself must be customized
    • make creates the plan, make! fills in properties

Customization

Users can customize serialization by:

  1. Defining StructUtils.lower for specific types:

    StructUtils.lower(::RecoPlanStyle, x::MyType) = Dict("special" => x.value)
  2. Defining StructUtils.lift for specific types:

    StructUtils.lift(::RecoPlanStyle, ::Type{MyType}, dict) = MyType(dict["special"]), dict
  3. Defining custom plan styles extending CustomPlanStyle:

    struct MyStyle <: CustomPlanStyle end
    StructUtils.lower(::MyStyle, x) = StructUtils.lower(RecoPlanStyle(), x)

    Styles based on CustomPlanStyle default to RecoPlanStyle.

Plan Levels

The serialization system supports two levels of style customization:

  • plan_style: Controls how plans are built and which style's make/make! methods are used
  • field_style: Controls how field values (parameters, algorithms) are serialized/deserialized

These are passed to savePlan and loadPlan:

savePlan(io, plan; plan_style=MyPlanStyle(), field_style=MyFieldStyle())
loaded = loadPlan(io, modules; plan_style=MyPlanStyle(), field_style=MyFieldStyle())

Example

plan = toPlan(algo)
savePlan("myplan.toml", plan)
loaded = loadPlan("myplan.toml", [MyModule, OtherModule])
source
AbstractImageReconstruction.CustomPlanStyleType
CustomPlanStyle

Abstract type for custom plan serialization styles.

Subtypes of CustomPlanStyle can override StructUtils.lower, StructUtils.make! and StructUtils.lift to provide custom serialization and deserialization behavior for specific types.

Use CustomPlanStyle when you need different serialization for certain fields while keeping the standard plan structure. The default delegation to RecoPlanStyle is provided for convenience.

Example

struct CustomStyle <: CustomPlanStyle end

StructUtils.lower(::CustomStyle, x::SpecialType) = Dict("custom" => x.data)

loadPlan("plan.toml", modules; field_style=CustomStyle())
source
AbstractImageReconstruction.savePlanFunction
savePlan(file::Union{AbstractString, IO}, plan::RecoPlan; plan_style=RecoPlanStyle(), field_style=RecoPlanStyle())

Save the plan to the file in TOML format.

Keywords

  • plan_style: Style for plan-level serialization (controls how RecoPlan instances are built)
  • field_style: Style for field-level serialization (controls how parameter and algorithm fields are serialized)

See also loadPlan, RecoPlanStyle.

source
AbstractImageReconstruction.loadPlanFunction
loadPlan(filename::Union{AbstractString, IO}, modules::Vector{Module}; plan_style=RecoPlanStyle(), field_style=RecoPlanStyle())

Load a RecoPlan from a TOML file. The modules argument is a vector of modules that contain the types used in the plan. After loading the plan, the listeners are attached to the properties using loadListener!.

Keywords

  • plan_style: Style for plan-level deserialization (controls how RecoPlan instances are built)
  • field_style: Style for field-level deserialization (controls how parameter and algorithm fields are deserialized)

Example

plan = loadPlan("myplan.toml", [MyModule, OtherModule])
source
AbstractImageReconstruction.parentpropertiesFunction
parentproperties(plan::RecoPlan)

Return a vector of property names of plan in its parent, s.t. getproperty(parent(plan), last(parentproperties(plan))) === plan. Return an empty vector if plan has no parent.

source

Miscellaneous

AbstractImageReconstruction.LinkedPropertyListenerType
LinkedPropertyListener(fn, target::RecoPlan, targetProp, source::RecoPlan, sourceProp)

Connect two properties of RecoPlans. Set target.targetProp to fn(source.sourceProp) whenever source.sourceProp changes and target.targetProp was not changed outside of the listener.

source
AbstractImageReconstruction.ProcessResultCacheType
ProcessResultCache(params::AbstractImageReconstructionParameters; maxsize = 1, kwargs...)

Cache of size maxsize for the results of parameter calls:

(params::P)(algo, inputs...)

The cache key is based on the hash of the algorithm (or its type), the wrapped parameter, and the inputs.

The same ProcessResultCache instance can be shared between algorithms constructed from the same plan. The cache is transparent with respect to the properties of the underlying parameter. Cached entries can be invalidated by calling empty!(params). (Shallow) copies a RecoPlan{ProcessCache} share a cache instance.

source
AbstractImageReconstruction.toKwargsMethod
toKwargs(value::AbstractImageReconstructionParameters; kwargs...)

Convert a AbstractImageReconstructionParameters to a Dict{Symbol, Any} of each property.

Optional keyword arguments:

  • flatten::Vector{DataType}: Types to flatten, per default only AbstractImageReconstructionParameters are flattened.
  • ignore::Vector{Symbol}: Properties to ignore.
  • default::Dict{Symbol, Any}: Default values for properties that are missing.
  • overwrite::Dict{Symbol, Any}: Overwrite values for properties.
source