Geometry

SwissVAMyKnife.ParallelRayOpticsType
ParallelRayOptics(angles, μ, DMD_diameter)

Type to represent the parallel ray optical approach. This is suited for a printer with an index matching bath. This is equivalent to an inverse (attenuated) Radon transform as the forward model of the printer.

  • angles is a range or Vector (or CuVector) storing the illumination angles.
  • DMD_diameter is the diameter of the DMD along the vial radius. So this is not the height along the rotation axis!
  • μ is the absorption coefficient of the resin in units of inverse meters So μ=100.0 1/m means that after 10mm of propagation the intensity is I(10mm) = I_0 * exp(-10.0mm * 100.0/m) = I_0 * exp(-1).

See also VialRayOptics for a printer without index matching bath.

Examples

julia> ParallelRayOptics(range(0, 2π, 401)[begin:end-1], 1 / 256)
ParallelRayOptics{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}(0.0:0.015707963267948967:6.267477343911637, 0.00390625)

julia> ParallelRayOptics(range(0, 2π, 401)[begin:end-1], nothing)
ParallelRayOptics{Nothing, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}}(0.0:0.015707963267948967:6.267477343911637, nothing)
source
SwissVAMyKnife.VialRayOpticsType

Type to represent a ray optical approach where refraction and reflection intensity loss at the glass vial is considered. This is equivalent to an inverse (attenuated) Radon transform as the forward model of the printer.

  • angles is a range or Vector (or CuVector) storing the illumination angles.
  • μ is the absorption coefficient of the resin in units of inverse meters So μ=100.0 1/m means that after 10mm of propagation the intensity is I(10mm) = I_0 * exp(-10.0mm * 100.0/m) = I_0 * exp(-1).
  • R_outer is the outer radius of the glass vial.
  • R_inner is the inner radius of the glass vial.
  • DMD_diameter is the diameter of the DMD along the vial radius. So this is not the height along the rotation axis!
  • n_vial is the refractive index of the glass vial.
  • n_resin is the refractive index of the resin.
  • polarization=PolarizationRandom() is the polarization of the light. See Polarization for the options.

Examples

julia> VialRayOptics(angles=range(0,2π, 501)[begin:end-1],
                     μ=nothing,
                     R_outer=6e-3,
                     R_inner=5.5e-3,
                     DMD_diameter=2 * R_outer,
                     n_vial=1.47,
                     n_resin=1.48,
                     polarization=PolarizationRandom()
                     )
source
SwissVAMyKnife.WaveOpticsType
WaveOptics(;z, λ, L, μ=nothing, angles)

Parameters

  • z: the different depths we propagate the field. Should be Vector or range.
  • λ: wavelength in the medium. So divide by the refractive index!
  • L: The side length of the array. You should satisfy L ≈ abs(z[begin]) + abs(z[end])
  • μ: Absorption coefficient.
  • angles: the angles we illuminate the sample. Should be Vector or range.
source
SwissVAMyKnife.PolarizationType
Polarization
  • PolarizationParallel() describes a parallel polarization.
  • PolarizationPerpendicular() describes a perpendicular polarization.
  • PolarizationRandom() describes a random polarization.
source

Optimization

SwissVAMyKnife.optimize_patternsFunction
optimize_patterns(target, ps::WaveOptics, op::GradientBased, loss::Union{LossThreshold, LossThresholdSparsity})

Optimize the patterns to match the target with the wave optical model. target is the target intensity. ps is the wave optical model. op is the optimization method. loss is the loss function.

source
optimize_patterns(target, ps::{VialRayOptics, ParallelRayOptics}, op::GradientBased, loss::LossTarget)

Function to optimize a target volume. This method returns the optimized patterns, the printed intensity and the optimization result.

See VialRayOptics how to specify the geometry of the vial. See ParallelRayOptics how to specify the geometry of the vial.

See PropagationScheme for the options for the different propagation schemes. See OptimizationScheme for the options for the different optimization schemes. See LossTarget for the options for the different loss functions.

Examples

julia> patterns, printed_intensity, res = optimize_patterns(target, VialRayOptics(angles=range(0,2π, 501)[begin:end-1],
                     μ=nothing,
                     R_outer=6e-3,
                     R_inner=5.5e-3,
                     n_vial=1.47,
                     n_resin=1.48,
                     polarization=PolarizationRandom()
                     ), GradientBased(), LossThreshold())
source
optimize_patterns(target::AbstractArray{T}, ps::ParallelRayOptics, op::OSMO) where T

Optimize patterns with the OSMO optimization algorithm. This is only supported for ParallelRayOptics.

Examples

julia> optimize_patterns(target, ParallelRayOptics(range(0, 2π, 401)[begin:end-1], 1 / 256), OSMO())
source

Optimizer

SwissVAMyKnife.GradientBasedType
GradientBased(; optimizer=LBFSG(), options=Optim.options(iterations=30, store_trace=true))

Define parameters for the GradientBased optimization algorithm. Optim.jl is used for the optimization. L-BFGS is the default optimizer which performs well for the optimization of the reconstruction problem. 30 iterations are used as default. The trace of the optimization is stored by default.

Example

julia> GradientBased(; optimizer=LBFGS(), options=Optim.Options(iterations=30, store_trace=true))
source
SwissVAMyKnife.OSMOType
OSMO(; iterations=10, thresholds=(0.7f0, 0.8f0))

Define parameters for the OSMO optimization algorithm. We recommend to use GradientBased instead of OSMO.

Reference

Rackson, Charles M., et al. Object-space optimization of tomographic reconstructions for additive manufacturing. Additive Manufacturing 48 (2021): 102367.

source

Loss Function

SwissVAMyKnife.LossThresholdType
LossThreshold(;sum_f=abs2, thresholds=(0.65f0, 0.75f0))

Loss function for polymerization. Keeps the object voxels in the range [T_U, 1] and the empty space in the range [0, T_L].

\[\mathcal{L} = \underbrace{\sum_{v \,\in\,\text{object}} |\text{ReLu}(T_U - I_v)|^K}_\text{force object polymerization} + $$ $$+\underbrace{\sum_{v\,\notin\,\text{object}} |\text{ReLu}(I_v - T_L) |^K}_{\text{keep empty space unpolymerized}} +\]

\[+\underbrace{\sum_{v \,\in\,\text{object}} |\text{ReLu}(I_v - 1)|^K}_{\text{avoid overpolymerization}}\]

  • The default K=2 corresponds to sum_f=abs2.
  • (T_L, T_U) = thresholds
julia> l = LossThreshold(thresholds=(0.5, 0.7))
LossThreshold{typeof(abs2), Float64}(abs2, (0.5, 0.7))

julia> x = [1.0, 0.0, 0.55]
3-element Vector{Float64}:
 1.0
 0.0
 0.55

julia> target = [1, 0, 1]
3-element Vector{Int64}:
 1
 0
 1

julia> l(x, target, nothing)
0.022499999999999975

julia> (0.7 - 0.55)^2
0.022499999999999975
source