Basic Reconstruction

MPIReco.jl provides different reconstruction interfaces. All of the interfaces interact with RecoPlans from AbstractImageReconstruction. These are blueprints from which different algorithms can be constructed. from which different algorithms can be constructed. For more details on these blueprints, we refer to the AbstractImageReconstruction documentation.

The reconstruction algorithm in MPIReco mainly focus on system-matrix based reconstructions, where one considers an inverse problem of the form:

\[\begin{equation} \underset{\mathbf{c}}{argmin} \frac{1}{2}\vert\vert \mathbf{S}\mathbf{c}-\mathbf{u} \vert\vert_2^2 + + \mathbf{R(x)} \end{equation}\]

where $\mathbf{S}$ is a system matrix, $\mathbf{u}$ is the measurement vector, and $\mathbf{R(x)}$ is an (optional) regularization term.

MPIReco comes with a few prepared blueprints, however one can easily add and store their own blueprints. These can be new configurations of existing algorithms and parameters or even new ones developed in other packages. Such packages could provide algorithms which are not based on system-matrix reconstructions. To read more on how to write and integrate such packages, consult the How-Tos.

High-Level Interface

In the Getting Started section, we created our first MPI reconstruction as follows:

c = reconstruct("SinglePatch", b;
                   SNRThresh=5,
                   sf = bSF,
                   frames=1:acqNumFrames(b),
                   minFreq=80e3,
                   recChannels=1:rxNumChannels(b),
                   iterations=1,
                   spectralLeakageCorrection=true);
[ Info: Loading SM
[ Info: Preparing SF
[ Info: Adapting SF

"SinglePatch" here refers to a blueprint for system-matrix based single-patch image reconstruction. The keyword arguments are used to set parameters defined in the blueprint.

It is also possible to provide these parameters as a dictionary. This is especially helpful if you want to reuse parameters or change parameters programmatically.

parameters = Dict{Symbol, Any}()
parameters[:SNRThresh] = 5
parameters[:sf] = bSF
parameters[:frames] = 1:acqNumFrames(b)
parameters[:minFreq] = 80e3
parameters[:recChannels] = 1:rxNumChannels(b)
parameters[:iterations] = 1
parameters[:spectralLeakageCorrection] = true;

You can just pass the dictionary as an argument to the reconstruct function as follows:

c2 = reconstruct("SinglePatch", b; parameters...)
isapprox(c.data, c2.data)
true

It is also possible to combine both methods of defining parameters:

c3 = reconstruct("SinglePatch", b; parameters..., recChannels = 1:1)
c3.rxNumChannels
3

Here, we overwrote the recChannels parameter within in the dictionary.

We can retrieve a list of all available blueprints that MPIReco can find using:

getRecoPlanList()
7-element Vector{String}:
 "Parameters.toml"
 "LowLevel.toml"
 "MultiPatch.toml"
 "MultiPatchMotion.toml"
 "SinglePatch.toml"
 "SinglePatchHandsFree.toml"
 "SinglePatchSparse.toml"

This list returns the filenames of the blueprints. In the reconstruct call, you only need to refer to the name without an extension.

To get the full paths of each blueprint, use:

planpaths = getRecoPlanList(;full=true)
7-element Vector{String}:
 "/home/runner/work/MPIReco.jl/MP" ⋯ 27 bytes ⋯ "ed/explanations/Parameters.toml"
 "/home/runner/work/MPIReco.jl/MPIReco.jl/config/LowLevel.toml"
 "/home/runner/work/MPIReco.jl/MPIReco.jl/config/MultiPatch.toml"
 "/home/runner/work/MPIReco.jl/MPIReco.jl/config/MultiPatchMotion.toml"
 "/home/runner/work/MPIReco.jl/MPIReco.jl/config/SinglePatch.toml"
 "/home/runner/work/MPIReco.jl/MPIReco.jl/config/SinglePatchHandsFree.toml"
 "/home/runner/work/MPIReco.jl/MPIReco.jl/config/SinglePatchSparse.toml"

You can add custom directories for MPIReco to search for blueprints. Other packages might do this automatically when they are loaded.

It is also possible to specify a direct path to a blueprint in the reconstruct function.

index = findfirst(endswith("SinglePatch.toml"), planpaths)
c4 = reconstruct(planpaths[index], b; parameters...)
isapprox(c.data, c4.data)
true

RecoPlan Interface

You can also directly access a blueprint via:

plan = MPIRecoPlan("SinglePatch")
RecoPlan{SinglePatchReconstructionAlgorithm}
└─ parameter::RecoPlan{SinglePatchParameters}
   ├─ reco::RecoPlan{SinglePatchReconstructionParameter}
   │  ├─ solverParams::RecoPlan{ElaborateSolverParameters}
   │  │  ├─ solver
   │  │  ├─ iterations
   │  │  ├─ enforceReal
   │  │  ├─ enforcePositive
   │  │  ├─ callbacks
   │  │  ├─ normalizeReg
   │  │  ├─ randomized
   │  │  ├─ subMatrixFraction
   │  │  ├─ shuffleRows
   │  │  ├─ seed
   │  │  ├─ greedy_randomized
   │  │  └─ theta
   │  ├─ weightingParams::RecoPlan{NoWeightingParameters} [Cached, 1]
   │  ├─ reg
   │  ├─ sf
   │  ├─ arrayType
   │  └─ sfLoad::RecoPlan{DenseSystemMatixLoadingParameter} [Cached, 3]
   │     ├─ tfCorrection
   │     ├─ loadasreal
   │     ├─ freqFilter::RecoPlan{SNRThresholdFrequencyFilterParameter}
   │     │  ├─ numPeriodAverages
   │     │  ├─ numPeriodGrouping
   │     │  ├─ maxMixingOrder
   │     │  ├─ numSidebandFreqs
   │     │  ├─ SNRThresh
   │     │  ├─ minFreq
   │     │  ├─ recChannels
   │     │  └─ maxFreq
   │     ├─ bgCorrection
   │     └─ gridding::RecoPlan{SystemMatrixGriddingParameter}
   │        ├─ fov
   │        ├─ deadPixels
   │        ├─ gridsize
   │        └─ center
   ├─ post::RecoPlan{NoPostProcessing}
   └─ pre::RecoPlan{CommonPreProcessingParameters} [Cached, 1]
      ├─ tfCorrection
      ├─ neglectBGFrames
      ├─ numPeriodAverages
      ├─ numPeriodGrouping
      ├─ numAverages
      ├─ spectralLeakageCorrection
      ├─ bgParams::RecoPlan{NoBackgroundCorrectionParameters}
      ├─ frames
      └─ loadasreal

This allows you to see all parameters associated with the blueprint and configure them individually. The keyword arguments previously mentioned apply to all parameters with the same name. Note that different parameters in different contexts can share the same name in RecoPlans.

To modify specific parameters of the plan, you can directly access its properties:

plan.parameter.reco.sf = bSF
MDFFile
	Study: "FocusField", Dates.DateTime("2014-11-13T16:20:01.217")
	Experiment: "SF_DF10_Middle (E39)", Dates.DateTime("2014-11-19T19:31:31.527")

Although we only updated the system matrix parameter, the plan now also includes derived values from the system matrix, such as the grid size.

plan.parameter.reco
RecoPlan{SinglePatchReconstructionParameter}
├─ solverParams::RecoPlan{ElaborateSolverParameters}
│  ├─ solver
│  ├─ iterations
│  ├─ enforceReal
│  ├─ enforcePositive
│  ├─ callbacks
│  ├─ normalizeReg
│  ├─ randomized
│  ├─ subMatrixFraction
│  ├─ shuffleRows
│  ├─ seed
│  ├─ greedy_randomized
│  └─ theta
├─ weightingParams::RecoPlan{NoWeightingParameters} [Cached, 1]
├─ reg
├─ sf = MDFFile
	Study: "FocusField", DateTime("2014-11-13T16:20:01.217")
	Experiment: "SF_DF10_Middle (E39)", DateTime("2014-11-19T19:31:31.527")

├─ arrayType
└─ sfLoad::RecoPlan{DenseSystemMatixLoadingParameter} [Cached, 3]
   ├─ tfCorrection
   ├─ loadasreal
   ├─ freqFilter::RecoPlan{SNRThresholdFrequencyFilterParameter}
   │  ├─ numPeriodAverages
   │  ├─ numPeriodGrouping
   │  ├─ maxMixingOrder
   │  ├─ numSidebandFreqs
   │  ├─ SNRThresh
   │  ├─ minFreq = 0.0
   │  ├─ recChannels
   │  └─ maxFreq = 1.25e6
   ├─ bgCorrection
   └─ gridding::RecoPlan{SystemMatrixGriddingParameter}
      ├─ fov = [0.04, 0.04, 0.001]
      ├─ deadPixels
      ├─ gridsize = [32, 32, 1]
      └─ center = [0.0, 0.0, 0.0]

This worked because the SinglePatch blueprint has connections between parameters. These connections depend on the blueprint itself and are not hardcoded in MPIReco.

You can also utilize the previously created dictionary to configure the plan:

setAll!(plan, parameters)

Alternatively, you can set all parameters of a specific name directly:

setAll!(plan, :iterations, 3)

Once the plan is configured, you can construct an algorithm from it using:

algo = build(plan);
[ Info: Loading SM
[ Info: Preparing SF
[ Info: Adapting SF

After constructing the algorithm, you can perform multiple reconstructions and reuse the algorithm with:

c = reconstruct(algo, b);

Depending on the algorithm, it might be faster to reconstruct multiple measurements from a RecoPlan, instead of the high-level interface. For more information on that, we refer to the How-To for caching. Algorithms are usually thread-safe, though they might not necessarily run concurrently.


This page was generated using Literate.jl.