Synthetic Data & Noise
Phantoms are functions $x \mapsto \sigma(x)$ that do not depend on a mesh. They are put on a discretization by conductivity (cell averages for piecewise constants). This makes it easy to simulate data on a finer mesh than the reconstruction mesh, with the same physical electrodes (transfer_electrodes), and so avoid the inverse crime:
coarse, fine = FerriteDiscretization(grid_coarse), FerriteDiscretization(grid_fine)
els = angular_electrodes(coarse, 16; coverage = 0.5)
fm = ForwardModel(coarse, CompleteElectrodeModel(els, 0.1))
fm_f = ForwardModel(fine, CompleteElectrodeModel(transfer_electrodes(coarse, els, fine), 0.1))
phantom = random_inclusions(rng; count = 1:3) # or gaussian_random_field, image_phantom
currents = trigonometric_patterns(fm, 7)
noise = RelativeGaussianNoise(0.01)
sim = simulate_data(fine, fm_f, phantom, currents; noise, rng)
data = AdjointStateObjective(fm, currents, sim.data)
res = minimize(RegularizedObjective(data, 1e-4 => TotalVariationRegularizer(coarse; ε = 1e-2)),
ones(ndofs_σ(coarse)), GaussNewton(); lower = 0.05,
ftarget = discrepancy_target(data, noise)) # discrepancy principleThe discrepancy target only accounts for the instrument noise. When the modelling error (for example of a coarse reconstruction mesh) is larger than the noise, the data have to be explained beyond what the model can represent, and the reconstruction deteriorates. Compare the model error norm(sim.clean - forward_neumann(fm, conductivity(coarse, phantom), currents)[1]) with the noise level before choosing the target.
Noise models
ModularEIT.AbstractNoiseModel — Type
AbstractNoiseModelMeasurement noise added to simulated data: GaussianNoise, RelativeGaussianNoise, SourceMeterNoise. See add_noise and simulate_data.
ModularEIT.GaussianNoise — Type
GaussianNoise(s)Additive white Gaussian noise with standard deviation s: a scalar, a vector with one standard deviation per measurement channel (data row), e.g. from an instrument specification, or a matrix with one per data entry (e.g. the noise of rotated data, see pattern_svd).
ModularEIT.RelativeGaussianNoise — Type
RelativeGaussianNoise(δ)Additive Gaussian noise relative to the signal level: for every pattern (column) fᵢ with m entries, ηᵢ ~ N(0, (δ ‖fᵢ‖ / √m)² I), so that ‖ηᵢ‖ ≈ δ ‖fᵢ‖ (e.g. δ = 0.01 for 1 % noise).
ModularEIT.SourceMeterNoise — Type
SourceMeterNoise(source, meter)Errors of the current source and of the voltmeter (or, for voltage-driven data, of the voltage source and the ammeter), each a GaussianNoise standard deviation (scalar or per channel): the applied inputs are inputs + source ε (projected back to zero net current for current patterns), the measurements F(applied) + meter ε. The reconstruction is given the nominal inputs. Needs the forward model, so it is applied by simulate_data.
ModularEIT.add_noise — Function
add_noise(data, noise; rng = Random.default_rng())
add_noise!(data, noise; rng = Random.default_rng())Noisy copy of data (or data overwritten) for an additive noise model (GaussianNoise, RelativeGaussianNoise). Pass a seeded rng for reproducible noise.
ModularEIT.expected_squared_error — Function
expected_squared_error(noise, data)Expected squared norm E‖η‖² (summed over all entries) of the noise that noise adds to data.
ModularEIT.discrepancy_target — Function
discrepancy_target(obj::AdjointStateObjective, noise; τ = 1.1)Target value of the objective for the discrepancy principle: τ² E[J(σ_true)], the expected misfit of exact data corrupted by noise, taken in the objective's metric (the whitening of its misfit and, for voltages, the removal of the weighted mean). Pass it as ftarget to minimize to stop when the data are explained to the noise level (τ slightly above 1). Relative noise levels are evaluated on the objective's (noisy) data.
discrepancy_target(obj::ApproximationErrorObjective; τ = 1.1)τ² m / 2 for m residuals: the expected misfit of the whitened residual.
ModularEIT.perturb_boundary_operator — Function
perturb_boundary_operator(R, s; rng = Random.default_rng())Operator-level noise for a discrete boundary operator (e.g. an estimated Neumann-to-Dirichlet matrix): R + s (Ê + Êᵀ)/2 with i.i.d. standard normal Ê. Symmetry is preserved, positive semidefiniteness is not (for large s).
Modelling errors
ModularEIT.perturb_contact_impedance — Function
perturb_contact_impedance(model::CompleteElectrodeModel, s; rng = Random.default_rng())Complete electrode model with log-normally perturbed contact impedances zₗ exp(s εₗ), a modelling error for data simulation (the reconstruction keeps the nominal model).
ModularEIT.electrode_angles — Function
electrode_angles(L; offset = 0, jitter = 0, rng = Random.default_rng())Centre angles offset + 2π(ℓ-1)/L + jitter εₗ of L electrodes, with Gaussian position errors of standard deviation jitter (radians); pass them as angles to angular_electrodes.
ModularEIT.transfer_electrodes — Function
transfer_electrodes(src, electrodes, dst)The electrodes of src as electrodes of the discretization dst of the same domain (e.g. a finer mesh for simulated data). Back end contract.
Approximation-error model
The modelling error of the reconstruction model (coarser mesh, pixels, …) as a Gaussian, from samples simulated with both models (Kaipio–Somersalo), with a leave-one-out variance floor for the directions the samples do not span:
R = reduce(hcat, [residual!(zeros(m), obj_i, θ_i) for (obj_i, θ_i) in samples]) # noise-free fine data
ae = ApproximationError(R; noise = η)
aobj = ApproximationErrorObjective(obj, ae)
res = minimize(aobj, θ0, GaussNewton(; linear_solver = :cg); ftarget = discrepancy_target(aobj))ModularEIT.ApproximationError — Type
ApproximationError(R; noise, floor = :leave_one_out, rtol = 1e-10)Gaussian model N(μ, Γ) of the modelling error from samples: the columns of R are residuals of the reconstruction model at the true parameters of sample conductivities, for noise-free data of the accurate model (e.g. a finer mesh). noise is the standard deviation η of the measurement noise per residual entry. Stores the mean μ and the low-rank factor of the whitening C^{-1/2}, C = (η² + ν²) I + Γ̂ (see whiten), with the sample covariance Γ̂ and a variance floor ν² for the directions the samples do not span: estimated by leave-one-out (floor = :leave_one_out: the mean squared part of a sample outside the span of the other samples, per remaining dimension; conservative, since the span of the other samples is itself perturbed), or given as a number (floor = 0: none). Singular values below rtol times the largest are dropped.
ModularEIT.whiten — Function
whiten(ae, r)The whitened residual C^{-1/2} (r - μ) of the ApproximationError ae.
ModularEIT.ApproximationErrorObjective — Type
ApproximationErrorObjective(obj, ae)The least-squares objective obj with the modelling error of ae accounted for: residual C^{-1/2}(r - μ), so that the misfit of the true conductivity is of the size of the noise again. Values, gradients, Jacobians (explicit and matrix-free, jacobian_operator), column norms and Gram matrices, so that all Gauss–Newton variants apply. Stop by the discrepancy principle with discrepancy_target(obj; τ) (the whitened residual has unit variance per entry).
ModularEIT.discrepancy_target — Method
discrepancy_target(obj::ApproximationErrorObjective; τ = 1.1)τ² m / 2 for m residuals: the expected misfit of the whitened residual.
Phantoms
ModularEIT.AbstractInclusion — Type
AbstractInclusionA shape with a conductivity value for InclusionPhantom: CircleInclusion, EllipseInclusion, PolygonInclusion. Membership: x in inclusion.
ModularEIT.CircleInclusion — Type
CircleInclusion(center, radius, value)Disc inclusion with conductivity value.
ModularEIT.EllipseInclusion — Type
EllipseInclusion(center, (a, b), angle, value)Elliptic inclusion with semi-axes a (along the direction angle) and b.
ModularEIT.PolygonInclusion — Type
PolygonInclusion(vertices, value)Polygonal inclusion (simple polygon, vertices in order) with conductivity value.
ModularEIT.InclusionPhantom — Type
InclusionPhantom(background, inclusions)Piecewise constant conductivity: background outside all inclusions, the value of the last inclusion containing x otherwise (later inclusions are painted on top). Callable: ph(x).
ModularEIT.random_inclusions — Function
random_inclusions(rng = Random.default_rng(); count = 1:3, domain = :disk, center = (0, 0),
radius = 1, bbox = (-1, 1, -1, 1), sizes = (0.1, 0.35), values = (0.2, 5.0),
background = 1, shapes = (:circle, :ellipse, :polygon), margin = 0.05,
separation = 0.05, maxtries = 1000)Random InclusionPhantom: rand(rng, count) non-overlapping inclusions of random shape (circles, ellipses with random orientation and aspect ratio, star-shaped polygons with 3–7 vertices) inside the domain (:disk with center and radius, or :box with bbox = (xmin, xmax, ymin, ymax)). Sizes (bounding radii) are drawn from sizes relative to the domain half-width, values log-uniformly from values. Every inclusion keeps the distance margin from the boundary and separation from the others; an inclusion that cannot be placed in maxtries attempts is dropped.
ModularEIT.PixelFunction — Type
PixelFunction(values; bbox = (-1, 1, -1, 1), interpolation = :nearest)Function on the rectangle bbox = (xmin, xmax, ymin, ymax) given by pixel values (row 1 at the top, as for to_image (Ferrite back end)), evaluated by :nearest pixel or :bilinear interpolation between pixel centres. Points outside the box take the value of the nearest border pixel.
ModularEIT.image_phantom — Function
image_phantom(img, σmin, σmax; bbox = (-1, 1, -1, 1), interpolation = :nearest)Conductivity from a grayscale image with intensities in [0, 1], mapped affinely to [σmin, σmax] (0 < σmin < σmax, so the forward problem stays elliptic), as a PixelFunction on bbox.
ModularEIT.gaussian_random_field — Function
gaussian_random_field(rng = Random.default_rng(); bbox = (-1, 1, -1, 1), ℓ = 0.2, order = 2,
pixel = ℓ / 10, pad = 3ℓ)Sample of a Gaussian random field with covariance (1 - ℓ²Δ)^(-order) (Matérn type: length scale ℓ, smoothness ν = order - 1 in 2D; order = 2 is the Whittle field, order = 1.5 the exponential covariance), scaled to unit marginal variance on average over bbox. Sampled on a pixel grid (size pixel) over bbox enlarged by pad in the cosine basis of the Neumann Laplacian, which keeps the reflecting boundary away from the box. Returns a bilinear PixelFunction; combine with lognormal_phantom or levelset_phantom.
ModularEIT.TransformedPhantom — Type
TransformedPhantom(f, g)The function x ↦ g(f(x)), e.g. a conductivity derived from a random field; see lognormal_phantom and levelset_phantom.
ModularEIT.lognormal_phantom — Function
lognormal_phantom(field; σ0 = 1, s = 0.5)Log-normal conductivity σ0 exp(s f(x)) from a (Gaussian random) field f.
ModularEIT.levelset_phantom — Function
levelset_phantom(field; level = 0, inside = 2, outside = 1)Two-phase conductivity: inside where f(x) > level, outside elsewhere. For a Gaussian random field this gives random inclusions with smooth, irregular boundaries.
Simulation
ModularEIT.conductivity — Function
conductivity(par::AbstractParametrization, θ)Conductivity coefficients σ = P θ of the parameters θ.
conductivity(disc, phantom; method = :l2, quadrature_order = 4)
conductivity(disc, σ::AbstractVector)Coefficients of a conductivity given as a function x ↦ σ(x) (a phantom, e.g. InclusionPhantom, PixelFunction, or any callable) in the σ space of disc: the L² projection (method = :l2, cell averages for piecewise constants, sampled with a rule of quadrature_order) or nodal interpolation (:interpolate). Coefficient vectors are passed through.
ModularEIT.simulate_data — Function
simulate_data(disc, fm, conductivity, inputs; mode = :neumann, noise = nothing,
rng = Random.default_rng(), solver = DirectSolver(), quadrature_order = 4)Simulated measurements for the forward model fm on disc: conductivity is a phantom (projected with conductivity) or a coefficient vector; inputs are current patterns (mode = :neumann, data = voltages) or voltage patterns (mode = :dirichlet, data = currents). noise: nothing, an additive AbstractNoiseModel or SourceMeterNoise.
Returns a named tuple (data, clean, σ, inputs, applied): noisy and exact data, the conductivity coefficients, the nominal inputs (to give to the reconstruction) and the inputs actually applied (different under source noise).
To avoid the inverse crime, simulate on a finer (or different) mesh than the reconstruction mesh: electrode patterns and electrode voltages do not depend on the mesh.
Image corruption
ModularEIT.corrupt_image — Function
corrupt_image(img; rng = Random.default_rng(), steps = 1, spatial_noise = 0.05,
spectral_noise = 0.01, damping = 1e-3, exponent = 1)Synthetic degradation of an image for training denoisers (wiki: Spectral Image Corruption). Repeats steps times: add white noise (spatial_noise), transform to the orthonormal DCT-II basis, add frequency-dependent noise spectral_noise (1 + |ω|²) ξ, damp by exp(-damping |ω|^(2 exponent)), transform back. |ω|² are the eigenvalues of the discrete Neumann Laplacian of the pixel grid, scaled to ≈ k² + l² for low frequencies (k, l), so damping alone (exponent = 1) is the discrete heat semigroup: it preserves the mean and satisfies the maximum principle.
Wiki articles
Theory behind this page in the theory wiki:
- Choosing the Regularization Parameter
- Spectral Sobolev Norms on Rectangles
- Stopping Criteria
- Noise Models for EIT Data
- Synthetic Conductivity Data
- Inverse Crime
- Approximation Error Approach
- Spectral Image Corruption
Index
ModularEIT.AbstractInclusionModularEIT.AbstractNoiseModelModularEIT.ApproximationErrorModularEIT.ApproximationErrorObjectiveModularEIT.CircleInclusionModularEIT.EllipseInclusionModularEIT.GaussianNoiseModularEIT.InclusionPhantomModularEIT.PixelFunctionModularEIT.PolygonInclusionModularEIT.RelativeGaussianNoiseModularEIT.SourceMeterNoiseModularEIT.TransformedPhantomModularEIT.add_noiseModularEIT.conductivityModularEIT.corrupt_imageModularEIT.discrepancy_targetModularEIT.discrepancy_targetModularEIT.electrode_anglesModularEIT.expected_squared_errorModularEIT.gaussian_random_fieldModularEIT.image_phantomModularEIT.levelset_phantomModularEIT.lognormal_phantomModularEIT.perturb_boundary_operatorModularEIT.perturb_contact_impedanceModularEIT.random_inclusionsModularEIT.simulate_dataModularEIT.transfer_electrodesModularEIT.whiten